第二章 经典同步问题1(生产者消费者、读者写者)

通过信号量的操作来完成经典同步问题。
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);
}

猜你喜欢

转载自blog.csdn.net/LIUPENGYUN/article/details/52976019