读者写者问题(读者优先/读写公平/写者优先)

First reader and writers problem (读者优先)

no reader be kept waiting unless a writer has obtain permission to write


semaphore rw=1, readcnt_m=1;
int readcnt=0;

Reader:

wait(readcnt_m);
readcnt++;
if(readcnt==1) wait(rw);
signal(readcnt_m);
read();
wait(readcnt_m);
readcnt--;
if(readcnt==0) signal(rw);
signal(readcnt_m);

Writer:

wait(rw);
write();
signal(rw);

readcnt_m 只是用来保护readcnt的数据一致性的,不必着重关注

rw相当于一个旗坑,要么插r表示在读,要么插w表示在写,插r只需要第一个人来插,最后一个走的人拔;插w表示在写,每个在写的人要单独插

读者来的时候判断自己是不是第一个读者,如果是它就必须抢 rw,因此 readcnt 的目的就是帮助读者判断自己是不是第一个读者,或者最后一个走的读者

这样就实现了最多有一个人同时写,但可以有多个人同时读,读和写不能同时发生

Q1:进程 P 在写,Q 可以读?

此时 rw 在 P 手上,此时 readcnt=0,Q 来了要去抢 rw,显然抢不到,所以阻塞

Q2:进程 P 在读,Q 可以读?

此时 readcnt>0,Q 不需要抢 rw,直接去读了


No-Starve readers and writers problem (读写公平)

in the version above, the writers may starve


int readcnt=0;
semaphore readcnt_m=1;
semaphore write_m=1;
semaphore wfirst_m=1;

Writer:

wait(wfirst_m);		// !
wait(write_m);

write();

signal(write_m);
signal(wfirst_m);	// !

Read:

wait(wfirst_m);		// !
signal(wfirst_m);	// !

wait(readcnt_m);
readcnt++;
if(readcnt==1) wait(write_m);
signal(readcnt_m);

read();

wait(readcnt_m);
readcnt--;
if(readcnt==0) signal(write_m);
signal(readcnt_m);

we just add wfirst_m

写者来了,如果写不了(write_m 被读者抢了),这时会把 wfirst_m 拿走,这样至少没有新的写者可以进入


Second readers and writers problem (写者优先)

once a writer is ready, the writer perform write as soon as possible


int readcnt=0;
semaphore readcnt_m=1;
semaphore read_m=1;

int writecnt=0;
semaphore writecnt_m=1;
semaphore write_m=1;

Writer:

wait(writecnt_m);
writecnt++;
if(writecnt==1) wait(read_m);
signal(writecnt_m);

wait(write_m);
write();
signal(write_m);

wait(writecnt_m);
writecnt--;
if(writecnt==0) signal(read_m);
signal(writecnt_m);

Reader:

wait(read_m);
wait(readcnt_m);
readcnt++;
if(readcnt==1) wait(write_m);
signal(readcnt_m);
signal(read_m);

read();

wait(readcnt_m);
readcnt--;
if(readcnt==0) signal(write_m);
signal(readcnt_m);

Q: 为什么上一个版本不是写优先,而这个版本是?

写者要访问的时候会抢走 read_m,直到没有写者访问时释放……所以 read_m 的作用就是保证在有写者在的时候没有读者可以执行

上一篇:【Linux学习笔记】kill及kill -9的用法及如何实现进程的优雅退出


下一篇:干货丨高频数据处理技巧:如何将高频信号转化为离散的买卖信号?