使用信号量实现生产者-消费者问题

问题描述:使用一个缓冲区来保存物品,只有缓冲区没有满,生产者才可以放入物品;只有缓冲区不为空,消费者才可以拿走物品。

因为缓冲区属于临界资源,因此需要使用一个互斥量 mutex 来控制对缓冲区的互斥访问。

为了同步生产者和消费者的行为,需要记录缓冲区中物品的数量。数量可以使用信号量来进行统计,这里需要使用两个信号量:empty 记录空缓冲区的数量,full 记录满缓冲区的数量。其中,empty 信号量是在生产者进程中使用,当 empty 不为 0 时,生产者才可以放入物品;full 信号量是在消费者进程中使用,当 full 信号量不为 0 时,消费者才可以取走物品。

注意,不能先对缓冲区进行加锁,再测试信号量。也就是说,不能先执行 down(mutex) 再执行 down(empty)。如果这么做了,那么可能会出现这种情况:生产者对缓冲区加锁后,执行 down(empty) 操作,发现 empty = 0,此时生产者睡眠。消费者不能进入临界区,因为生产者对缓冲区加锁了,消费者就无法执行 up(empty) 操作,empty 永远都为 0,导致生产者永远等待下,不会释放锁,消费者因此也会永远等待下去。

#define N 100
typedef int semaphore;
semaphore mutex = 1;
semaphore empty = N;
semaphore full = 0;void producer() {while(TRUE) {int item = produce_item();down(&empty);down(&mutex);insert_item(item);up(&mutex);up(&full);}
}void consumer() {while(TRUE) {down(&full);down(&mutex);int item = remove_item();consume_item(item);up(&mutex);up(&empty);}
}

使用管程实现

4. 管程

使用信号量机制实现的生产者消费者问题需要客户端代码做很多控制,而管程把控制的代码独立出来,不仅不容易出错,也使得客户端代码调用更容易。

c 语言不支持管程,下面的示例代码使用了类 Pascal 语言来描述管程。示例代码的管程提供了 insert() 和 remove() 方法,客户端代码通过调用这两个方法来解决生产者-消费者问题。

monitor ProducerConsumerinteger i;condition c;procedure insert();begin// ...end;procedure remove();begin// ...end;
end monitor;

管程有一个重要特性:在一个时刻只能有一个进程使用管程。进程在无法继续执行的时候不能一直占用管程,否者其它进程永远不能使用管程。

管程引入了 条件变量 以及相关的操作:wait() 和 signal() 来实现同步操作。对条件变量执行 wait() 操作会导致调用进程阻塞,把管程让出来给另一个进程持有。signal() 操作用于唤醒被阻塞的进程。

使用管程实现生产者-消费者问题

// 管程
monitor ProducerConsumercondition full, empty;integer count := 0;condition c;procedure insert(item: integer);beginif count = N then wait(full);insert_item(item);count := count + 1;if count = 1 then signal(empty);end;function remove: integer;beginif count = 0 then wait(empty);remove = remove_item;count := count - 1;if count = N -1 then signal(full);end;
end monitor;// 生产者客户端
procedure producer
beginwhile true dobeginitem = produce_item;ProducerConsumer.insert(item);end
end;// 消费者客户端
procedure consumer
beginwhile true dobeginitem = ProducerConsumer.remove;consume_item(item);end
end;

操作系统:生产者与消费者问题相关推荐

  1. 计算机操作系统生产者和消费者模型的简单介绍

    同步互斥小口诀 画图理解题目 判断题目类型 分析进程数目 填写进程模板 补充基本代码(伪代码) 补充PV代码 检查调整代码 注意事项 代码是一步一步写出来的,代码是反复调整写出来的 60%是生产者和消 ...

  2. 操作系统生产者与消费者问题代码实现

    问题分析: ①假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品.缓冲池被占用时,任何进程都不能访问. ② ...

  3. 生产者和消费者代码———操作系统_操作系统基础15-生产者消费者问题

    在上一篇操作系统基础14提到通过信号量解决生产者消费者问题.本篇来详细说说操作系统中的经典问题-生成者消费者问题 生产者消费者问题 (Producer-consumer problem) 该问题是一个 ...

  4. Linux并发程序课程设计报告,网络操作系统课程设计--进程机制与并发程序设计-linux下生产者与消费者的问题实现.doc...

    网 络 操 作 系 统 课 程 设 计 网络操作系统课程设计 设计内容:进程机制与并发程序设计inux下生产者与消费者的问题实现进程机制与并发程序设计inux下生产者与消费者的问题实现 (1)掌握基本 ...

  5. 操作系统生产者消费者问题实验报告

    操作系统实验报告 进程通信 1. 问题描述及需求分析: 问题描述 本次实验实现生产者和消费者之间的通信,即生产者-消费者问题.生产者一次生成一个元素放入缓冲池中,消费者一次可以从缓冲池中取出一个元素. ...

  6. 操作系统 —— 生产者消费者模型

    文章目录 1. 生产者消费者模型的理解 1.1 串行的概念 1.2 并行的概念 1.3 简单总结: 2. 基于阻塞队列(block queue)实现此模型 2.1 阻塞队列的实现 2.2 使用阻塞队列 ...

  7. 【SEUSE】操作系统实验:消费者-生产者问题

    操作系统实验:消费者-生产者问题 README 一.实验目的 二.实验内容 三.实验步骤 四.主要数据结构及其说明 五.程序运行时的初值和运行结果 六.实验体会 七.源程序 README 本实验报告仅 ...

  8. 操作系统实验之生产者和消费者程序

    这是我的操作系统实验课的实验之一,实验要求"实现生产者和消费者程序". 老师给了我们示例程序,要求我们自己修改调试.程序代码如下,已经在本地linux系统上能够正确运行. p是模拟 ...

  9. (二十三)操作系统-多生产者·多消费者问题

    文章目录 一.问题描述 二.问题分析 1. 关系分析 2. 整理思路 三.实现 1. 代码 2.如果不要互斥信号量 3. 将盘子(缓冲区)容量设为2 四.总结 一.问题描述   桌子上有一只盘子,每次 ...

最新文章

  1. redis 双写一致性
  2. 深度学习七个实用技巧
  3. php 连接mysql 错误排查一例
  4. 三个单词说的英语口语
  5. mysqldump导出数据库视图_mysql数据库的基本操作:索引、视图,导入和导出,备份和恢复...
  6. 使用javamail进行邮件发送
  7. PHP通过PDO连接Microsoft Access数据库
  8. python中fd和rt是什么意思_python中fd()是什么
  9. vue踩坑-This relative module was not found
  10. 【线程】——单例模式
  11. 再见Windows C++
  12. JNI在C和C++的env语法
  13. LINUX虚拟机安装增强功能时报错: Kernel headers not found for target kernel. Please install them and execute
  14. 00006__WindowsAPI 之 CreatePipe、CreateProcess
  15. 龙格-库塔(Runge-Kutta)方法C++实现
  16. 事务前沿研究 | 隔离级别的追溯与究明,带你读懂 TiDB 的隔离级别(下篇)
  17. 与虎谋皮,饮鸩止渴,却有什么办法呢?
  18. 浅谈Docker的安全性支持(上篇)
  19. Android 一键拨号
  20. Java面试练习题(每天进步一点点)

热门文章

  1. Sylius不需要缓存使用默认地址
  2. 监听应用是否切到后台
  3. Jupyter Notebook 快速入门简易教程
  4. Ubuntu16.04 LTS安装配置安装CUDA8.0、CUDNN5.1
  5. 图书馆为什么使用sip2协议_RFID无人智能借还书柜让微型图书馆“触手可及”
  6. bogofilter 使用
  7. Zynq器件的时钟系统
  8. Linux 发行版与Linux内核
  9. 【DP优化】【P1430】序列取数
  10. iOS之coreData