允许多个进程同时对数据进行读操作,但是不允许读和写以及写和写操作同时发生。
一个整型变量 count 记录在对数据进行读操作的进程数量,一个互斥量 count_mutex 用于对 count 加锁,一个互斥量 data_mutex 用于对读写的数据加锁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| typedef int samephore;
void down(int* x){} void up(int* y){}
int count = 0; samephore count_mutex = 1; samephore data_mutex = 1;
void reader(){ while(true){
down(&count_mutex); count ++; if(count==1) down(&data_mutex); up(&count_mutex); down(&count_mutex); count --; if(count==0) up(&data_mutex); up(&count_mutex); } } void writer(){ while(true){ down(&data_mutex); up(&data_mutex); } }
|
此解法中读者是优先的,当存在读者时,写者将被延迟,且只要有一个读者活跃,随后而来的读者都将被允许访问此文件,从而导致写者长时间等待,并有可能出现写者饥饿现象。
增加信号量并修改此程序,让写者与读者平等:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| samephore s = 1;
void reader(){ while(true){ down(&s); down(&count_mutex); count ++; if(count==1) down(&data_mutex); up(&count_mutex); up(&s);
down(&count_mutex); count --; if(count==0) up(&data_mutex); up(&count_mutex); } } void writer(){ while(true){ down(&s); down(&data_mutex); up(&data_mutex); up(&s); } }
|
假设进程队列:R1、W1、W2、R2、R3
当R1刚刚执行完V(s),W1进程若调度会卡在P(writeblock),而W2R2R3想要运行,均会卡在P(s),当R1读完,V(writeblock)完成,W1可以运行,以此类推,R1W1W2R2R3按顺序调度。