从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机相关技巧
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • 最全面的 RSS 教程
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金
  • 职场规划
  • 关于离职
  • 杂谈
  • 自媒体
  • 📖 读书

    • 读书工具
    • 走进科学
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
    • 读书笔记
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机相关技巧
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • 最全面的 RSS 教程
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金
  • 职场规划
  • 关于离职
  • 杂谈
  • 自媒体
  • 📖 读书

    • 读书工具
    • 走进科学
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
    • 读书笔记
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • 计算机简史

  • 数字电路

  • 计算机组成原理

  • 操作系统

    • 我的操作系统学习笔记

    • 我的操作系统实验笔记

    • 操作系统网课-王道考研

      • 0_课程白嫖指南
      • 1_1_操作系统的概念(定义)、功能和目标
      • 1_2_操作系统的特征
      • 1_3_操作系统的发展与分类
      • 1_4_操作系统的运行机制与体系结构
      • 1_5_中断和异常
      • 2_1_6_系统调用
      • 2_1_1_进程的定义、组成、组织方式、特征
      • 2_1_2_进程的状态与转换
      • 2_1_3_进程控制
      • 2_1_4_进程通信
      • 2_1_5_线程概念和多线程模型
      • 2_2_1_处理机调度的概念、层次
      • 2_2_2_进程调度的时机、切换与过程、方式
      • 2_2_3_调度算法的评价指标
      • 2_2_4_FCFS、SJF、HRRN调度算法
      • 2_2_5_调度算法:时间片轮转、优先级、多级反馈队列
      • 2_3_1_进程同步、进程互斥
      • 2_3_2_进程互斥的软件实现方法
      • 2_3_3_进程互斥的硬件实现方法
      • 2_3_4_信号量机制
      • 2_3_5_用信号量实现进程互斥、同步、前驱关系
      • 2_3_6_生产者-消费者问题
      • 2_3_7_多生产者-多消费者问题
      • 2_3_8_吸烟者问题
        • 小结
      • 2_3_9_读者-写者问题
      • 2_3_10_哲学家进餐问题
      • 2_3_11_管程
      • 2_4_1_死锁的概念
      • 2_4_2_死锁的处理策略—预防死锁
      • 2_4_3_死锁的处理策略—避免死锁
      • 2_4_4_死锁的处理策略—检测和解除
      • 3_1_1_内存的基础知识
      • 3_1_2_内存管理的概念
      • 3_1_3_覆盖与交换
      • 3_1_4_连续分配管理方式
      • 3_1_5_动态分区分配算法
      • 3_1_6_基本分页存储管理的基本概念
      • 3_1_7_基本地址变换机构
      • 3_1_8_具有快表的地址变换机构
      • 3_1_9_两级页表
      • 43_3_1_10_基本分段存储管理方式
      • 3_1_11_段页式管理方式
      • 3_2_1_虚拟内存的基本概念
      • 3_2_2_请求分页管理方式
      • 3_2_3_页面置换算法
      • 3_2_4_页面分配策略
      • 4_1_1_初识文件管理
      • 4_1_2_文件的逻辑结构
      • 4_1_3_文件目录
      • 4_1_4_文件的物理结构(上)
      • 4_1_4_文件的物理结构(下)
      • 54_4_1_5_文件存储空间管理
      • 4_1_6_文件的基本操作
      • 4_1_7_文件共享
      • 4_1_8_文件保护
      • 4_1_9_文件系统的层次结构
      • 4_2_1_磁盘的结构
      • 4_2_2_磁盘调度算法
      • 4_2_3_减少磁盘延迟时间的方法
      • 4_2_4_磁盘的管理
      • 5_1.2_I-O 控制器
      • 5_1.3_I-O 控制方式
      • 65_5_1_1_I-O 设备的概念和分类
      • 5_1_4_I-O 软件层次结构
      • 5_1_5_I-O 核心子系统
      • 5_1_6_假脱机技术
      • 5_1_7_设备的分配与回收
      • 5_1_8_缓冲区管理
  • Linux

  • 计算机网络

  • 数据库

  • 编程工具

  • 装机

  • 计算机基础
  • 操作系统
  • 操作系统网课-王道考研
2023-05-15
目录

238_吸烟者问题

# 2.3_8_吸烟者问题

各位同学大家好。在这个小节中我们会学习一个进程同步互斥的问题叫做吸烟者问题。

程对缓冲区的访问一定这种关系。

一个系统当中有三个抽烟者进程和一个供应者进程,每个抽烟者进程都会不停的卷烟,并且把它抽掉,但是要卷起一支烟,抽烟者需要三种材材料,烟草纸和胶水。

这三个抽烟者分别拥有烟草、纸和胶水这样的材料,但每个抽烟者都缺少另外两种材料,而供应者他会无限的为这三个抽烟者提供他们所需要的材料,供应者会往这个桌子上放两种材料,比如说是纸和胶水,那么这两种材料是第一个抽烟者所需要的,所以第一个抽烟者会把这两种材料从桌子上取走,并且把它卷成香烟,然后抽掉。当他完成吸烟之后,吸烟者进程,他会向供应者进程发出一个信号,告诉他当前抽烟已经完成了。

​

那么供应者进程又会往桌子上放入下一组材料,比如说是烟草和胶水,那么这两个材料是二号抽烟者所需要的,所以他会从桌子上取走这两个材料,并且把它卷成香烟吸掉。和刚才一样,他也会通知供应者,现在吸烟已经完成

​ ‍

那么供应者又会接着往这个桌子上放下一种组合的材料烟草和纸,这个是三号抽烟者所需要的,所以他会把这个材料给取走,并且卷成香烟吸掉。

​ ‍

那么每一个抽烟者进程只会从桌子上拿走自己所需要的那两种材料,而这个供应者进程它需要让三个抽烟者轮流的吸烟,也就是说他需要轮流的为第一个进程进程提供他所需要的两种之后,又为进程提供他所需要的两种,再之后又为进程提供他所需要的两种,然后再来一个轮回,不断的无限的循环。

有没有发现这个问题其实也是一个生产者消费者的问题,供应者相当于是一个生产者,而这些吸烟者相当于是一个消费者,但是与之前咱们所介绍的生产者消费者模型不同的是,这个生产者他可能会生产三种不同的产品。 ‍ 那么我们根据之前学过的那种思路来依次进行分析。首先题目当中所描述的进程总共有 4 个,很显然 1 个供应者进程和 3 个抽烟者进程,他们之间是否有同步互斥的关系,由于供应者进程每次只能往桌子上放一种材料的组合,所以我们可以把桌子看作是一种容量为 1,初始为空的缓冲区,而对缓冲区的访问需要互斥的进行,咱们在之前已经强调过这个问题。

为什么说它的容量唯一不是说桌子上每次会放两种材料吗?其实这个题目当中我们不能把两种材料看作是两种独立的物品,我们应该把它看作是一种组合。比如说纸和胶水的组合,我们就把它看作一个整体,称为组合一,组合一是抽烟者一需要使用的,而烟草和胶水的组合我们把它称为组合二,这是抽烟者二所需要的。组合三也一样,它是抽烟者三所需要的,所以其实我们不应该说这个桌子上可以同时放两种材料,而应该说这个桌子上同一时刻只能放其中某一种组合,我们把这些组合看作一个整体,这是这个题目当中隐含的一个互斥问题。

接下来我们再来看一下同步问题,只有桌子上有组合一,这个事件发生的时候,才可以发生第一个抽烟者取走东西这个事件。同样的,只有桌子上有组合二,只有这个事件发生的时候才可以接着发生,第二个抽烟者取走东西这个事件。那么对于这三对一前一后的这种同步关系来说,我们需要对这些关系各自设置一个同步变量。

另外题目当中还给了一个条件,只有抽烟者卷了一根烟,并且把它抽掉之后,他才会给供应者进程发送一个信号,告诉他现在抽烟已经完成了,之后供应者才会把接下来的两种材料放到桌上,所以发出完成信号这个事件发生之后,供应者才可以把下一个组合放到桌子上,所以这是第四个同步关系。

​ ‍

那么第二步我们再来看一下大体需要执行哪些 pv 操作。对于实现互斥的 pv 操作来说很简单,无非就是在访问临界资源的之前和访问临界资源之后,对互斥信号量分别执行 p 和 v 操作。

而对于同步问题来说,我们需要遵循前 v 后 p 这样的原则,必须发生在前面的事件发生了之后,我们需要执行一个 v 操作,而必须发生在后面的事件发生之前,我们需要执行一个 p 操作。

那么接下来我们就需要确定各个信号量的初始值到底是多少。对于互斥问题来说,由于缓冲区的大小唯一,所以我们即使不设置专门的互斥变量,其实也可以实现互斥访问临界区这件事情,咱们在之前小节已经介绍过类似的问题,所以我们只考虑设置这些同步信号量

​

桌上有组合一,这个事件必须发生在第一个抽烟者取走东西这个事件之前,所以对于这一对同步关系来说,我们需要为它设置一个同步信号量叫做 offer1,那么刚开始桌子上是没有组合一的,这个事件只能由供应者来触发,所以同步信号量的初始值我们应该把它设置为 0。而第二个和第三个关系也和刚才的类似,我们分别为这两对同步关系设置 offer2 和 offer3 这两个同步信号量,而初始值和刚才一样都是设为 0。

第四对同步关系发出完成信号这个事件要发生在供应者将下一个组合放到桌上这个事件之前。而发出完成信号,这个事件可以由这三个吸烟者当中的任何一个来触发。所以这三个吸烟者进程都需要对与这个事件相关的同步信号量执行一个 v 操作,而后面这个放入材料的事件只能由供应者来执行,所以供应者需要对这个事件对应的同步信号量执行一个 p 操作。那么由于刚开始并没有任何一个吸烟者进程发出了完成信号,所以我们为它设置的同步变量是 finish 的初始值也是 0

​ ‍

接下来我们再来看一下具体的代码实现。我们分别定义了 offer1、offer2 和 offer3,这三个同步信号量分别用来表示桌子上组合一、组合二、组合三的数量。另外还设置了一个叫做 finish 的同步信号量,用来表示此时这些抽烟者抽烟这个事件是否完成。

另外题目当中有个条件,说供应者需要轮流的给三个抽烟者供应材料,让三个抽烟者轮流的吸烟,所以我们设置一个 int 型的变量,用于实现三个抽烟者轮流抽烟这个事情。供应者每一次在桌上放了某一种组合之后,都需要对 i 这个变量执行加一,并且对三取余的这种操作,每一个循环就会使 I 的值变为 012,012 这样循环。那么如果这次循环中 i 的值为 0,那么供应者就就把组合一放在桌上,也就是让第一个吸烟者来吸烟。

如果 i 的值为一,那么它就让第二个吸烟者吸烟。i 的值为二,就让第三个吸烟者吸烟。而刚才我们也说过,i 的值会按照 012,012 这样的循环来往复的变化,所以这就可以实现供应者轮流的让三个吸烟者吸烟这件事情。

​ ‍

当供应者在桌上放入了某一种组合之后,它需要对这个组合对应的同步信号量执行一个 v 操作,用来通知等待这种组合的吸烟者。另外供应者把材料放到桌上之后,它需要等待吸烟者向他发出完成吸烟的信号。所以在最后这个地方我们又需要对 finish 信号量执行一个 p 操作。

而各个吸烟者在从桌子上拿走材料之前,需要检查此时桌子上放的是不是自己所需要的材料。当把这些材料拿走,并且抽掉之后,又需要向供应者发出一个完成信号来通知,供应者可以开始放下一个材料了。

所以由于刚开始 finish 这个信号量是 0,所以供应者它在放完第一组材料之后,它会在这个地方被阻塞,一直等到第一个吸烟者从桌上拿走组合一并且卷烟抽掉之后,他又会对 finish 执行 v 操作,从而又重新让供应者进程从阻塞态又回到就绪态,然后又可以进行下一轮的供给。而对于另外两个吸烟者来说,他们所做的事情和第一个吸烟者其实也类似,这就不再展开赘述。

这个地方大家再结合这些代码来分析一下,到底是不是需要专门的设置一个斥信号量,才可以保证各个进程他们互斥的访问桌子缓冲区。其实如果经过分析之后,大家会发现这些信号量同一时刻,只会至多只有一个的值可能是一,也就是说这 4 个进程在同一时刻最多只会有其中的 1 个不被 p 操作所阻塞,可以顺利的进入桌子临界区,这个地方感兴趣的大家可以自己再推一下。

​ ‍

# 小结

吸烟者问题为我们解决,可以生产多个产品的单生产者这种问题提供了一个可以参考的思路。那么我们比较值得借鉴的是这个题目当中我们是如何实现轮流让各个吸烟者吸烟的。我们设置了一个整形变量 i,并且我们让整型变量 i 按照 012,012 这样的顺序来循环的改变它的值,这样就实现了轮流让各个吸烟者吸烟这个需求。

如果说题目改为每次供应者会随机的让一个吸烟者吸烟的话,我们应该怎么写这个代码逻辑呢?其实在咱们的王道书上是写了一个 random 变量,这个 random 变量是一个随机数,但是题目中要求我们实现的是轮流让各个吸烟者吸烟,所以我认为王道书上给的代码逻辑应该是实现了每次随机的让一个吸烟者吸烟,而如果要轮流的让个吸烟者吸烟的话,我们需要按照刚才咱们讲的那种逻辑来实现。

另外如果一个生产者要生产多种产品或者说一个进程,它有可能会引发多种前驱事件。所谓的前驱事件就是说这个事件发生了之后,另一个事件才可以发生。那么在这种情况下,我们就要在各个前驱事件发生之后的位置,加上与它对应的 v 操作,就像这个题目当中供应者的那几个 v 操作一样,这是吸烟者问题值得大家借鉴的地方

​ ‍

上次更新: 2025/5/9 14:55:39
2_3_7_多生产者-多消费者问题
2_3_9_读者-写者问题

← 2_3_7_多生产者-多消费者问题 2_3_9_读者-写者问题→

最近更新
01
学点统计学:轻松识破一本正经的胡说八道
06-05
02
2025 年 5 月记
05-31
03
《贫穷的本质》很棒,但可能不适合你
05-27
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式