读者写者问题

问题描述

image.png

问题分析

这个问题,互斥问题是主要要考虑的事情。

难点 1:有多个读者,数量不定。无法使用固定数量的信号量表示。

互斥:

代码实现

不合理实现

sem rw = 1; // 用于解决写者和读者的互斥
sem mutex = 1;
int count = 0; // 表示当前有多少的读者

void writer() {
	while (1) {
		P(rw);
		...
		V(rw);
	}
}

void reader() {
	while (1) {
		P(mutex);
		if (count == 0) {
			P(rw);
		}
		count++;
		V(mutex);
		
		P(mutex);
		count--;
		if (count == 0) {
			V(rw);
		}
		V(mutex);
	}
}
解读

上述实现会出现的问题是如果有源源不断地读进程加入,就会一直不释放 rw,从而导致写进程一直无法工作,造成饥饿的现象。

优化实现

解决办法就是让写进程优先。即加上同步关系,让写进程在任何时候都有机会进行写操作。

sem w = 1;

void writer() {
	while (1) {
		P(w);
		P(rw);
		...
		V(rw);
		V(w);
	}
}

void reader() {
	while (1) {
		P(w);
		
		P(mutex);
		if (count == 0) {
			P(rw);
		}
		count++;
		V(mutex);
		
		V(w);
		
		读文件...
		
		P(mutex);
		count--;
		if (count == 0) {
			V(rw);
		}
		V(mutex);
	}
}
解读
  1. 当写进程占据了 w 后,读进程无法继续增加,当写进程进一步占据 rw 后,所有读进程就无法继续执行读操作了。
  2. 若读进程率先占据 w,那么写进程因为 w 而阻塞。此时读进程继续占据 rw,但是随后将释放 w,此时写进程就可以占据w,以防止其他读进程继续改变 count 值。当那个释放 w 的读进程释放了 rw 后,写进程就必然可以进行工作。
  3. 可以用并发顺序:读者1->写者1->读者2,进行模拟运行。