通过信号量的操作来完成经典同步问题。
1、生产者-消费者问题(北邮自主命题2016年考过,可能17年不考)
描述:
*一组生产者生产产品,一组消费者消费产品
*同一时间只能有一个生产者或消费者访问缓冲池
*当缓冲池满,生产值阻塞,缓冲池空,消费者阻塞
实现方法
Semaphore full=0; //满缓冲区数目
Semaphore empty=n; //空缓冲区数目
Semaphore mutex=1;
Producter()
{
while(true)
{
生产一个产品;
P(empty); //一定是先申请空缓冲池再放入
P(mutex); //互斥实现产品放入缓冲池
讲产品放入缓冲池;
V(mutex);
V(full);
}
}
Consumer()
{
while(true)
{
P(full);
P(mutex);
将产品取出缓冲池;
V(mutex);
V(empty);
消费产品;
}
}
在生产者消费者问题上,P操作是不能替换顺序的(可能导致死锁),V可以。大题的原则是一定要先对资源信号量进行P操作,在对互斥信号量进行P操作。
2、读者-写者问题(2017年考试可能性很大)
描述
*任意时刻多个读者可以同时读文件
*任意时刻只能有一个写者写文件
*写操作时不能读,读操作时不能写
这个问题呢,分多种情况实现,读者优先、公平情况和写者优先,其实懂了精髓的话,这几个的差别是比较微小的。
(1)读优先
Semaphore rmutex=1;
Semaphore mutex=1;
Semaphore readcount=0;
Reader()
{
while(true)
{
P(rmutex);
if(readercount==0) //如果是第一个进行读操作的,阻止写者进入
P(mutex);
readcount++;
V(rmutex);
开始读文件;
P(mutex); //注意每次进行readcount计数时都要对rmutex互斥
readcount--;
if(readcount == 0) //如果我是最后一个读者,就通知写者可以进来了
V(mutex);
}
}
Writer()
{
while(true)
{
P(mutex);
进行写操作;
V(mutex);
}
}
(2)公平情况算法(按到达顺序操作)
进程执行顺序完全按照到达顺序,一个读者进行读操作时,如果有一个写者正在写或者再等,这个读者排在他后面。
需要增设一个信号量wmutex,初值为1,表示是否存在正在写或者在等的写者,存在则禁止读者进入。
Semaphore mutex=1;
Semaphore rmutex=1; //用于读者互斥访问readcount
Semaphore wmutex=1; //用于写者互斥访问readcount
int readcount;
Reader()
{
while(true)
{
P(wmutex); //如果此时有写操作,那么会被堵塞
P(rmutex);
if(readcount == 0) //如果是第一个读进程,不准写者进入
P(mutex);
readcount++;
V(rmutex); //这里要恢复rmutex
V(wmutex);
进行读操作;
P(rmutex);
readcount--;
if(readcount==0)
V(mutex); //如果没有读者了,允许写者进入
V(rmutex);
}
}
(3)写者优先
写者可以插队到读者队列之前,无论写者是什么时候来的。
这里呢,需要再增加一个信号量readable,控制写者到达时有限进入临界区。
Semaphore mutex=1; //控制互斥访问数据区
Semaphore rmutex=1; //用于读者互斥访问readcount
Semaphore wmutex=1; //用于写者互斥访问readcount
Semaphore readable=1; //表示当前是否有写者
int readcount=0,writecount=0; //记录读者和写者的数量
Reader()
{
P(readable); //没有写者才继续操作
P(rmutex);
if(readcount==0)
P(mutex);
readcount++;
V(rmutex);
V(readable); //释放readable让其他读者可以使用
读操作;
P(rmutex);
readcount--;
if(readcount==0)
V(mutex);
V(rmutex);
}
Writer()
{
P(wmutex);
if(writecount==0) //如果为第一个写者,阻止后续读者进入
P(readable);
writecount++;
V(wmutex);
P(mutex);
写数据;
V(mutex);
P(rmutex);
writecount--;
if(writecount==0)
V(readable);
V(wmutex);
}