• 生产者-消费者问题(操作系统)


    生产者-消费者问题从特殊到一般(从易到难)可以分3种形式:

    一个生产者、一个消费者、一个缓冲区的问题;

    一个生产者、一个消费者、n个缓冲区的问题;

     k个生产者、m个消费者、n个缓冲区的问题;

    当缓冲区空时,生产者可将产品存入缓冲区;当缓冲区满时,生产者必须等待 (阻塞),待消费者取走产品后将其唤醒后,才能将产品存入。

    当缓冲区有产品时,消费者可从缓冲区取出产品进行消费;当缓冲区空时,消费者必须等待 ( 阻塞 ) ,待生产者存入产品后将其唤醒后,才能再从缓冲区取产品。

    1. 为生产者设置 1 个私有信号量 empty ,其初值为 1 ,表示有 1 个空缓冲区;为消费者设置 1 个私有信号量 full ,其初值为 0 ,表示开始时没有满缓冲区;( 信号量初值由物理意义确定
    2. 生产者将产品存入缓冲区之前,应先 测试 缓冲区是否空:执行 wait(empty) 操作;离开临界区 ( 存入产品 ) 后,应 通知 ( 可能会唤醒 ) 消费者:执行 signal(full) 操作;
    3. 消费者从缓冲区取产品之前,应先 测试 缓冲区是否满:执行 wait(full) 操作;离开临界区 ( 取走产品 ) 后,应 通知 ( 可能会唤醒 ) 生产者:执行 signal(empty) 操作

    一个生产者、一个消费者、一个缓冲区


    生产者消费者问题的算法描述如下所示:

    初始化设置

    1. semaphore empty,full;
    2. empty=1;full=0;

    生产者

    1. parbegin
    2. process Producer:
    3. {
    4. produce an item in nextp;
    5. wait(empty);//测试
    6. buffer=nextp;
    7. signal(full);//通知消费者
    8. }

    消费者

    1. process Consumer:
    2. {
    3. wait(full); //测试
    4. nextc=buffer;
    5. signal(empty); //通知
    6. consume the item
    7. in nextc;
    8. }
    9. parend

    信号量机制解决进程同步问题的一般方法:

    1. 为同步双方设置各自的信号量,初值为其初始状态可用的资源数 ( 故该信号量称为 资源信号量 私有信号量 )
    2. 同步双方任一进程在进入临界区之前,应先对自己的信号量执行 wait(< 己方信号量 >) 操作,以 测试 是否有自己可用的资源。若有资源可用,则进入临界区,否则阻塞;
    3.同步双方任一进程离开临界区后,应对合作方 (对方)的信号量执行signal(<对方信号量>)操作,以通知(若对方处于阻塞状态,则唤醒它)对方已有资源可用(对方已可进入临界区)。

    一个生产者、一个消费者、n个缓冲区


            为生产者设置一个资源信号量empty ,其初值为生产者的可用资源数 ( 空缓冲区的个数 )n ,即 empty=n
            为消费者设置一个资源信号量full ,其初值为消费者的可用资源数 ( 满缓冲区的个数 )0 ,即 full=0

    生产者消费者问题的算法描述如下所示:

    初始化设置

    1. ​​​​​​​semaphore empty,full;
    2. empty=n;full=0;
    3. int in=0,out=0;   //下标

    生产者

    1. parbegin
    2. process Producer:
    3. {
    4. produce an item in nextp;
    5. wait(empty);//测试
    6. buffer[in]=nextp;
    7. in=(in+1)%n;
    8. signal(full);//通知消费者
    9. }

    消费者

    1. process Consumer:
    2. {
    3. wait(full); //测试
    4. nextc=buffer[out];
    5. out=(out+1)%n;
    6. signal(empty); //通知
    7. consume the item in nextc;
    8. }
    9. parend

    本题中inout不是共享变量(因为只有一个生产者和一个消费者),无需互斥访问。

    K个生产者、M个消费者、n个缓冲区


    1、设置生产者的资源信号量 empty ,其初值为 n ,表示开始时有 n 个空缓冲区;
    2、设置消费者的资源信号量 full ,其初值为 0 ,表示开始时有 0 个满缓冲区;
    3、只要有空的缓冲区,生产者便可将消息送入缓冲区;
    4、只要有满的缓冲区,消费者便可从缓冲区取走一个消息。
    5、用互斥信号量 mutex 对缓冲区 ( 共享变量 in out) 的互斥使用,互斥信号量 mutex 初值为 1
    6、生产者用共享变量 in 作为下标访问缓冲区, mutex 为其互斥信号量;消费者用共享变量 out 作为下标访问缓冲区,其互斥信号量也用 mutex

    初始化

    1. semaphore mutex,empty,full ;
    2. item buffer[n] ;
    3. int in = 0,out = 0
    4. mutex.value = 1;
    5. empty.value=n,full.value=0;

    生产者

    1. parbegin //并发执行开始
    2. process produceri (i=1,2,…,k) //生产者进程
    3. {
    4. item nextp;
    5. while (true)
    6. {
    7. produce an item nextp;
    8. wait(empty) ; //测试是否有可用的资源
    9. wait(mutex); //互斥(进入临界区)
    10. buffer[in] = nextp ;
    11. in = (in + 1)% n ;
    12. signal(mutex) ; //退出临界区
    13. signal(full) ; //通知(可能唤醒)协作方
    14. }
    15. }

    消费者

    1. process consumerj (j=1,2,…,m)
    2. { item nextc ;
    3. while (true) {
    4. wait(full); //测试是否有可用的资源
    5. wait(mutex);
    6. nextc = buffer[out] ;
    7. out = (out + 1)% n ;
    8. signal(mutex);//生产者消费者互斥访问缓冲区,同时生产者互斥生产,消费者户次消费
    9. signal(empty); //通知(可能唤醒)协作方
    10. consume the item in nextc ;
    11. }
    12. }
    13. parend //并发执行结束

    注意:


    在每个进程中,实现互斥的 wait(mutex) signal(mutex) 必须成对出现;
    对资源信号量 empty和full wait signal 操作也要成对地出现,但它们处于不同的进程中 ( 交叉成对 )
    在每个进程中的多个 wait 操作顺序不能颠倒,应先执行对资源信号量(也称私有信号量)的 wait 操作,然后执行对互斥信号量(公有信号量)的 wait 操作,否则可能引起进程死锁。

    重申信号量解决同步问题的要点:


    1. 为同步双方设置各自的信号量,初值为其初始状态可用的资源数 ( 故该信号量称为 资源信号量 私有信号量 )
    2. 同步双方任一进程在进入临界区之前,应先对自己的资源信号量执行 wait(< 己方信号量 >) 操作,以 测试 是否有自己可用的资源。若有资源可用,则进入临界区,否则阻塞;
    3. 同步双方任一进程离开临界区后,应对合作方 ( 对方 ) 的资源信号量执行 signal(< 对方信号量 >) 操作,以 通知 ( 若对方处于阻塞状态,则唤醒它 ) 对方已有资源可用 ( 对方已可进入临界区 )

  • 相关阅读:
    【CVPR 2022】QueryDet:加速高分辨率小目标检测
    分享一个Python Django影片数据爬取与数据分析系统源码
    第三章 循环
    图搜索算法 - 深度优先搜索法(DFS)
    Postman 从入门到进阶教程(万字长文)
    2022年安徽省技术创新示范企业奖励补贴标准以及申报条件(附合肥市各地区奖补标准)
    你知道Java 中为什么不全部使用 Static 方法吗?
    进入vue之前需要了解的打包工具
    云课五分钟-09Linux基础命令实践-AI助力快速入门
    痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(12)- 从SD/eMMC启动
  • 原文地址:https://blog.csdn.net/qq_50942093/article/details/127623584