“读者—写者”问题—记录型信号量
一个数据文件或记录可被多个进程共享。
- 只要求读文件的进程称为“Reader进程”,其它进程则称为“Writer进程”。
- 允许多个进程同时读一个共享对象,但不允许一个Writer进程和其他Reader进程或Writer进程同时访问共享对象
“读者—写者问题”是保证一个Writer进程必须与其他进程互斥地访问共享对象的同步问题。
读者—写者问题要解决:读、读共享;写、写互斥;写、读互斥。
①定义互斥信号量wmutex,实现写、写互斥和写、读互斥。
②定义整型变量Readcount表示正在读的进程数目。由于只要有一个Reader进程在读,便不允许Writer进程写,因此仅当Readcount=0,即无Reader进程在读时,Reader才需要执行Wait(wmutex)操作。若Wait(wmutex)操作成功,Reader进程便可去读,相应地,做Readcount+1操作。同理,仅当Reader进程在执行了Readcount减1操作后其值为0时,才需执行signal(wmutex)操作,以便让Write进程写。
③由于Readcount为多个读进程共享(修改),因此需要以互斥方式访问,为此,需要定义互斥信号量rmutex,保证读进程间互斥访问Readcount。
semaphore wmutex = 1;
semaphore rmutex = 1;
int readcount = 0;// 记录有几个读者
void reader()
{
while(true)
{
wait(rmutex); // rmutex是为了保护readcount共享变量
if(readcount == 0)
{
wait(wmutex);// 保证第一个读进程来,写进程就不能进行
}
readcount++;
signal(rmutex);
// 读的过程
wait(rmutex);
readcount--;
if(readcount == 0)
{
signal(wmutex); // 保证最后一个读进程读完,释放wmutex信号量
}
signal(rmutex);
}
}
void writer()
{
while(true)
{
wait(wmutex);
// 写的过程
signal(wmutex);
}
}
“读者—写者”问题—信号量集式信号量
增加一个限制:最多只允许RN个读者同时读。
引入信号量L,并赋予其初值RN,通过执行Swait(L, 1, 1)操作,来控制读者的数目。
每当有一个读者进入时,就要先执行Swait(L, 1, 1)操作,使L的值减1。当有RN个读者进入读后,L便减为0,第RN +1个读者要进入读时,必然会因Swait(L, 1, 1)操作失败而阻塞。
semaphore mx = 1;// 作为读写互斥的信号量
int L = 0;// 记录有几个读者
const int RN = 1000;
void reader()
{
while(true)
{
swait(L,1,1);
swait(mx,1,0); //一个开关,当mx>1时,才能读
// read
signal(L,1);
}
}
void writer()
{
while(true)
{
swait(mx,1,1;L,RN,0); // 当mx-1成功,并且L>=RN的时候才可以进行,此时说明没有读进程在读
// 写的过程
signal(mx,1);
}
}