1.要求
在Linux环境下,创建一个进程,此进程包含n个线程。用这n个线程来表示n个读者或写者。每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制(仅读者优先或写者优先):
1. 写-写互斥,即不能有两个写者同时进行写操作。
2. 读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
3. 读-读允许,即可以有一个或多个读者在读。
2.概念
读者优先:当有读者在等待队列里等待时,写者进程不能开始
写者优先:当有写者在等待队列里等待时,读者进程不能开始
3.伪代码
公平竞争
在没有特别的优先级情况下,读者写者公平竞争。进程之间通过wrt的锁保证临界区访问的互斥性,先获得wrt锁的进程先执行。
读者
wait(mutex);
++reader_count;
if(reader_count == 1) {
wait(&wrt);
}
signal(mutex);
// read
wait(mutex);
--reader_count;
if(reader_count == 0) {
signal(&wrt);
}
signal(mutex);
写者
wait(&wrt);
// write
signal(&wrt);
读者优先
读者优先和写者优先需要引入一个状态变量state,表明当前系统的状态。需要用到的几个状态量如下:
- mutex:保证reader_count, writer_count, state变量访问的互斥性
- Sig_read:允许读的信号量
- Sig_wrt:允许写的信号量
读者
wait(mutex);
++reader_count;
if(state == s_waiting || state == s_reading) {
signal(Sig_read);
state = s_reading;
}
signal(mutex);
// read
wait(mutex);
--reader_count;
if(reader_count == 0) {
if(writer_count != 0) {
signal(Sig_wrt);
state = s_writing;
} else {
state = s_waiting;
}
}
signal(mutex);
写者
wait(mutex);
++writer_count;
if(state == s_waiting) {
signal(Sig_wrt);
state = s_writing;
}
signal(mutex);
// write
wait(mutex);
--writer_count;
if(reader_count != 0) {
signal(Sig_read);
state = s_reading;
} else if(writer_count != 0) {
signal(Sig_wrt);
state = s_writing;
} else {
state = s_waiting;
}
signal(mutex);
写者优先
读者
wait(mutex);
++reader_count;
if(state == s_waiting
|| (state == s_reading && writer_count == 0)) {
signal(Sig_read);
state = s_reading;
}
signal(mutex);
// read
wait(mutex);
--reader_count;
if(writer_count != 0) {
// 有读者在等待
sem_post(Sig_wrt);
state = s_writing;
} else if(reader_count == 0) {
// 等待队列为空
state = s_waiting;
}
signal(mutex);
写者
wait(mutex);
++writer_count;
if(state == s_waiting) {
signal(Sig_wrt);
state = s_writing;
}
signal(mutex);
// write
wait(mutex);
--writer_count;
if(writer_count != 0) {
signal(Sig_wrt);
state = s_writing;
} else if(reader_count != 0) {
for(int i=0; i!=reader_count; ++i) {
signal(Sig_read);
}
state = s_reading;
} else {
state = s_waiting;
}
signal(mutex);