生产者消费者问题

image.png

<aside> ❓

能否改变相邻 P、V 操作的顺序?

P 操作的顺序不能交换,否则发生死锁;V 操作的顺序可以交换

实现互斥的P操作一定要在实现同步的P操作之后,否则可能引起“死锁”

</aside>

<aside> 💡

使用产品操作不要放在临界区中,加锁的粒度尽量小

</aside>

多生产者多消费者

桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等着吃盘子中的橘子,女儿专等着吃盘子中的苹果。只有盘子空时,爸爸或妈妈才可向盘子中放一个水果。仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出水果。

  1. 找出同步、互斥关系

    互斥关系: 对缓冲区(盘子)的访问要互斥地进行 同步关系(一前一后): 1.父亲将苹果放入盘子后,女儿才能取苹果 2.母亲将橘子放入盘子后,儿子才能取橘子 3.只有盘子为空时,父亲或母亲才能放入水果

  2. 尝试优化:无需互斥信号量 mutex 也可以

    image.png

<aside> ❓

如果如果盘子容量为 2,还能取消掉 mutex 信号量吗?

不能,可能会出现两个生产者同时写入,覆盖对方的数据的情况

结论:如果缓冲区大小大于 1,就必须专门设置一个互斥信号量 mutex 来保证树池访问缓冲区

</aside>

吸烟者问题

假设一个系统有三个抽烟者进程和一个供应者进程。每个抽烟者不停地卷烟并抽掉它,但是要卷起并抽掉一支烟,抽烟者需要有三种材料:烟草、纸和胶水。三个抽烟者中,第一个拥有烟草、第二个拥有纸、第三个拥有胶水。供应者进程无限地提供三种材料,供应者每次将两种材料放桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它,并给供应者进程一个信号告诉完成了,供应者就会放另外两种材料再桌上,这个过程一直重复(让三个抽烟者轮流地抽烟)

image.png

image.png

<aside> ❓

如何实现轮流的需求?

通过代码中专门的变量 i 来实现

</aside>

读者写者问题

有读者和写者两组并发进程,共享一个文件,当两个或两个以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:①允许多个读者可以同时对文件执行读操作;②只允许一个写者往文件中写信息;③任一写者在完成写操作之前不允许其他读者或写者工作;④写者执行写操作前,应让己有的读者和写者全部退出

image.png

如何实现读写公平算法?

semaphore rw = 1;    // 用于实现对共享文件的互斥访问
int count = 0;       // 记录当前有几个读进程在访问文件
semaphore mutex = 1; // 用于保证对 count 变量的互斥访问
semaphore w = 1;     // 用于实现“写优先”

writer() {
    while (1) {
        P(w);
        P(rw);
        // 写文件...
        V(rw);
        V(w);
    }
}

reader() {
    while (1) {
        P(w);
        P(mutex);
        if (count == 0)
            P(rw);
        count++;
        V(mutex);
        V(w);
        // 读文件...
        P(mutex);
        count--;
        if (count == 0)
            V(rw);
        V(mutex);
    }
}

分析以下并发执行 P(w) 的情况: