经典同步问题 读者-写者问题

读者-写者问题

在读者-写者问题中,只对共享数据进行读取的进程为读者进程,修改共享数据的进程称为写者进程。多个读者可同时读取共享数据而不会导致出现错误,但是任何时刻多个写者进程不能同时修改数据,写者进程和读者进程也不能同时访问共享数据。读者-写者问题的解决策略有不同的倾向。

读者优先

需要用到的共享变量:

semaphore rw_mutex = 1;  // 读者与写者互斥访问共享数据的互斥信号量
semaphore mutex = 1;  // 多个读者进程互斥修改当前读者进程数量的信号量
int read_count = 0;  // 系统当前读者进程数量

写者进程结构

do {
	wait(rw_mutex);
	...
	/* 修改共享数据 */
	...
	signal(rw_mutex);
}while(true);

读者进程结构

do {
	wait(mutex);  // 获取修改读者进程数量的互斥信号量,该操作在请求rw_mutex之前,防止出现死锁
	read_count++;
	if(read_count == 1)  // 判断当前是否为第一个读者进程
		wait(rw_mutex);  // 如果是就需要请求访问共享数据的互斥信号量
	signal(mutex);  // read_count修改后释放信号量
	...
	/* 读取数据 */
	...
	wait(mutex);  // 获取修改读者进程数量的互斥信号量
	read_count--;
	if(read_count == 0)  // 判断当前进程是否为最后一个读者进程
		signal(rw_mutex);  // 如果是则释放共享数据的互斥信号量,以允许写者进程操作共享数据
	signal(mutex);
}while(true);

读者优先有可能导致写者进程产生饥饿现象,当系统中不断出现读者进程时,写者进程始终无法进入临界区。

写者优先

需要用到的共享变量:

semaphore rw_mutex = 1;     // 读者与写者互斥访问共享数据的互斥信号量
semaphore r_mutex = 1;      // 互斥修改当前读取文件的进程数
semaphore w_mutex = 1;      // 互斥修改当前修改文件的进程数
semaphore enter_mutex = 1;  // 获取申请访问文件的权限
int read_count = 0;         // 系统当前读者进程数量
int write_count = 0;        // 系统当前写者进程数量

写者进程结构

do {
    wait(w_mutex);  // 新的写者进程进入,获取修改写者进程数量的权限
    write_count++;
	if(write_count == 1)  // 判断当前是否为第一个写者进程
        wait(enter_mutex); // 阻断后续到达的读者进程
	signal(w_mutex);
    
    wait(rw_mutex);  // 获取访问文件的权限,文件可能被其它写者进程占用,或者等待最后一个读者进程释放
	...
	/* 修改数据 */
	...
	wait(rw_mutex);
    wait(w_mutex);
	write_count--;
	if(write_count == 0)  // 当所有写者进程都放弃使用文件时,运行读者进程申请访问文件
		signal(enter_mutex);
	signal(mutex);
}while(true);

读者进程结构

do {
    wait(enter_mutex);  // 获取申请访问文件的权限
    wait(r_mutex);
    read_count++;
	if(read_count == 1)  // 判断当前是否为第一个读者进程
        wait(rw_mutex);  // 占用文件
	signal(r_mutex);
    signal(enter_mutex);
	...
	/* 读取数据 */
	...
    wait(r_mutex);
	read_count--;
	if(read_count == 0)
		signal(rw_mutex);
	signal(r_mutex);
}while(true);

写者优先有可能导致读者进程产生饥饿现象,当系统中不断出现写者进程时,读者进程始终无法进入临界区。

读写公平

需要用到的共享变量:

semaphore rw_mutex = 1;     // 读者与写者互斥访问共享数据的互斥信号量
semaphore r_mutex = 1;      // 互斥修改当前读取文件的进程数
semaphore enter_mutex = 1;  // 获取申请访问文件的权限
int read_count = 0;         // 系统当前读者进程数量

写者进程结构

do {
    wait(enter_mutex);  // 阻断后续到达的读者进程
	wait(rw_mutex);
	...
	/* 修改数据 */
	...
    signal(rw_mutex);
	signal(enter_mutex);
}while(true);

读者进程结构

do {
    wait(enter_mutex);  // 获取申请访问的权限,这里与写者优先的区别在于,写者放弃占用文件时,所有读者                            都可以与写者进程进行再次竞争 
    wait(r_mutex);
    read_count++;
	if(read_count == 1)  // 判断当前是否为第一个读者进程
        wait(rw_mutex);
	signal(r_mutex);
    signal(enter_mutex);  // 释放许可,其余读者和写者进程将进行下一轮竞争
	...
	/* 读取数据 */
	...
    wait(r_mutex);
	read_count--;
	if(read_count == 0)
		signal(rw_mutex);
	signal(r_mutex);
}while(true);

posted @ 2020-03-30 16:11  我家的猫儿不吃鱼  阅读(486)  评论(0编辑  收藏  举报