经典同步问题

news2024/9/30 5:38:49

同步问题是一个复杂的问题,但是它也有自己的方法去处理、去分析。

PV操作系统的解题思路:

  1. 关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。(从事件的角度分析)

  1. 整理思路。根据各进程的操作流程确定P、V操作的大致顺序。

  1. 设置信号量。设置需要的信号量,并根据题目条件确定信号量的初值。(互斥信号量初值一般为1,同步信号量的初始值要看对应资源的初始值是多少)

1.生产者-消费者问题

问题描述:系统中有一组生产者进程和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓存区中取出一个产品并使用。(注:这里的"产品"理解为某种数据)

分析:

生产者、消费者共享一个初始为空、大小为n的缓冲区

只有缓冲区没满时,生产者才能把产品放到缓冲区,否则必须等待。(缓冲区没满->生产者生产)

只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。(缓冲区没空->消费者消费)

缓冲区是临界资源,各进程必须互斥的访问

根据分析,两个同步,一个互斥,所以需要3个信号量。定义如下:

semaphore mutex=1;//互斥信号量,实现对缓冲区的互斥访问
semaphore empty=n;//同步信号量,表示空闲缓冲区的数量
semaphore full=0;//同步信号量,表示产品的数量,也即非空缓冲区的数量
//生产者
Producer(){
    while(1){
          生产一个产品;
          P(mutex);
          P(empty);
          把产品放入缓冲区;
          V(mutex);
          V(full);
   }
}
//消费者
Consumer(){
     while(1){
     P(mutex);
     P(full);
     从缓冲区中取走一个产品;
     V(mutex);
     V(empty);
     使用产品;
}
}

注意实现互斥的P操作一定要在实现同步的P操作之后。否则会造成死锁的现象。(V操作不会导致进程阻塞,因此两个V操作顺序可以交换)。

2.多生产者-多消费者问题

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

分析:

互斥关系:对缓冲区(盘子)的访问要互斥地进行

同步关系(一前一后):

  1. 父亲将苹果放入盘子后,女儿才能取苹果。

  1. 母亲将橘子放入盘子后,儿子才能取橘子。

  1. 只有当盘子为空时,父亲或母亲才能放入水果。

根据分析,三个同步,一个互斥,所以需要个信号量。定义如下:

semaphore mutex=1;//实现互斥访问盘子(缓冲区)
semaphore apple=0;//盘子中有几个苹果  
semaphore orange=0;//盘子中有几个橘子
semaphore plate=1;//盘子中还可以放多少个水果

生产者、消费者定义如下:

Dad(){
  while(1){
     准备一个苹果;
     P(plate);
     P(mutex);
     把苹果放入盘子;
     V(mutex);
     V(apple);
  }
}
Mom(){
  while(1){
     准备一个橘子;
     P(plate);
     P(mutex);
     把橘子放入盘子;
     V(mutex);
     V(orange);
  }
Daughter(){
  while(1){
     P(apple);
     P(mutex);
     从盘子中取出苹果;
     V(mutex);
     V(palte);
     吃掉苹果;
  }
Son(){
  while(1){
     P(orange);
     P(mutex);
     从盘子中取出橘子;
     V(mutex);
     V(palte);
     吃掉橘子;
  }

注意:在本例子当中,如果不设置互斥信号量也是可以实现互斥的,原因是缓冲区大小是1,在任何时刻,三个同步信号量只有一个为1。

3.吸烟者问题

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

分析:

组合一:纸和胶水

组合二:烟草和胶水

组合三:烟草和纸

同步关系(从事件的角度分析):

  1. 桌子上有组合一->第一个抽烟者取走东西

  1. 桌子上有组合二->第二个抽烟者取走东西

  1. 桌子上有组合三->第三个抽烟者取走东西

  1. 发出完成信号->供应者将下一个组合放到桌上

和上题一样,本例子缓冲区大小为1,4个同步不信号量中同一时刻至多有一个值为1,所以不需要互斥信号量,定义如下:

semaphore offer1=0;//桌子上组合一的数量
semaphore offer2=0;//桌子上组合二的数量
semaphore offer3=0;//桌子上组合三的数量
semaphore finish=0;//抽烟是否完成
int i=0;//用于实现"三个抽烟者轮流抽烟"

供应者和抽烟者定义如下:

Provider(){
  while(1){
      if(i==0){
         将组合一放桌上;
          V(offer1);
          }
       else if(i==0){
         将组合二放桌上;
          V(offer2);
          }
       else if(i==0){
         将组合三放桌上;
          V(offer3);
          }
        i=(i+1)%3;
        P(finish)
  }
}
Smoker1(){
   while(1){
     P(offer1);
     从桌上拿走组合一、卷烟、抽掉;
     V(finish);
    }
}
Smoker2(){
   while(1){
     P(offer2);
     从桌上拿走组合二、卷烟、抽掉;
     V(finish);
    }
}
Smoker3(){
   while(1){
     P(offer3);
     从桌上拿走组合三、卷烟、抽掉;
     V(finish);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/174274.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java设计模式-备忘录模式、备忘录模式应用场景是什么、又怎么使用

继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用! 6.11 备忘录模式 6.11.1 定义 又称快照模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存此状态&…

深入学习Vue.js(十一)内建组件和模块

文章目录KeepAlive组件的实现原理1.KeepAlive组件实现原理2.KeepAlive组件的代码实现(1)shouldKeepAlive(2)keepAliveInstance(3)keptAlive(4)move函数3.include和exclude4.缓存策略…

视频生成动画数据OpenPose+OpenCV

我们只是使用OpenPose,不包括深度学习和代码的部分,会用就OK。 1.打开OpenPose的官网,直接进入安装页面,地址如下: OpenPose: OpenPose Doc - Installation 2.安装的说明,大家要好好看,我们就…

吴恩达机器学习课程笔记:多元梯度下降法

1.吴恩达机器学习课程笔记:多元梯度下降法 笔记来源:吴恩达机器学习课程笔记:多元梯度下降法 仅作为个人学习笔记,若各位大佬发现错误请指正 1.1 多元特征(变量) 每一列代表一个特征,例如&…

【Github CLI】Take GitHub to the command line

目录儿~一、Git、Github、GitLab二、Github CLI——gh2.1 gh简介2.2 gh的使用2.21 Github身份验证(必选)2.22 常用命令(1)在Github仓库中打开当前项目(2)gh配置 gh config(3)克隆仓库…

(16)go-micro微服务jaeger链路追踪

文章目录一 jaeger链路追踪介绍什么是链路追踪:链路追踪主要功能:二 jaeger链路追踪作用三 jaeger链路追踪主要特性四 jaeger链路追踪原理图1.链路调用原理2. 一次调用链分析3.链路追踪存储与调用五 jaeger链路追踪五个重要组件六 jaeger链路追踪安装1.d…

Junit框架

JUnit 是一个 Java 编程语言的单元测试框架。环境配置创建maven项目&#xff0c;导入Junit配置<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --> <dependency><groupId>org.junit.jupiter</groupId><artifactId&g…

Linux常用命令——tail命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) tail 在屏幕上显示指定文件的末尾若干行 补充说明 tail命令用于输入文件中的尾部内容。tail命令默认在屏幕上显示指定文件的末尾10行。如果给定的文件不止一个&#xff0c;则在显示的每个文件前面加一个文件名…

【docker概念和实践 4】 常见命令和案例(1)

一、说明 本篇讲述当Docker安装完成后&#xff0c;进行的由浅入深的操作过程。命令种类有&#xff1a;1 进程引擎进程命令 2帮助命令 3 镜像命令 4 容器命令 5 仓库命令。 二、关于操作引擎的指令 本节讲操作引擎的启动、关闭、维护等。以下两种形势都是等价的命令格式。 方法…

Java概览——Java运行机制

Java概览—Java运行机制Java的运行过程 Java程序运行时&#xff0c;必须经过编译和运行两个步骤。首先将后缀名为.java的源文件进行编译&#xff0c;最终生成后缀名为.class的字节码文件&#xff0c;然后Java虚拟机&#xff0c;将字节码文件进行解释执行&#xff0c;并将结果显…

Docker学习笔记【part1】概念与安装

一、Docker的概念 Docker 是实现系统平滑移植、容器虚拟化的技术&#xff0c;基于 Go语言&#xff0c;可以实现软件带环境安装&#xff0c;做到“一次镜像&#xff0c;处处运行”。Docker 是一个 C/S 模式的架构&#xff0c;后端是一个松耦合架构&#xff0c;众多模块各司其职…

九龙证券|次新股叠加智慧交通+信创+数字经济概念,开盘冲涨停!

核算机板块1月以来跑赢上证指数&#xff1b;才智交通、成绩高增及严重财物重组个股登上涨停榜。 证券时报•数据宝核算&#xff0c;1月19日&#xff0c;沪深两市收盘涨停股35只&#xff0c;其中ST股6只。群众交通、长久科技两股一字板强势涨停&#xff0c;潞安环能、跃岭股份收…

【MySQL】第五部分 多表查询

【MySQL】第五部分 多表查询 文章目录【MySQL】第五部分 多表查询5. 多表查询5.1 等值连接5.2 非等值连接5.3 自连接5.4 内连接5.5 外连接5.6 满外连接5.7 SQL99语法实现多表查询5.7.1 JOIN...ON语法5.7.2 使用SQL99语法实现内连接5.7.3 使用SQL99语法实现左外连接和右外连接5.…

postman入门

目录 新建界面 菜单区 百度翻译api实战 post 参数化 新建界面 1&#xff09;可以新建请求&#xff0c;&#xff08;rqueset&#xff09;模拟客户端的请求&#xff0c; 2&#xff09;可以创建测试集合&#xff08;collection&#xff09;&#xff0c;对接口请求进行统一管理…

删除排序链表中的重复元素

删除排序链表中的重复元素 题目描述 原始题目参考&#xff1a;删除有序链表的重复元素 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1…

java spring IOC Bean管理操作(xml P名称空间注入)

首先 我们来写一个基本的 通过xml的set属性注入 首先创建一个项目 然后引入 spring 最基本的几个依赖包 src下 下有一个 gettingStarted 包 下面有一个 user类 代码如下 package gettingStarted;public class user {public String name;public int age;public void setName(S…

leetcode 1817. 查找用户活跃分钟数【python3,哈希表的实现思路详解】

题目 给你用户在 LeetCode 的操作日志&#xff0c;和一个整数k。日志用一个二维整数数组logs表示&#xff0c;其中每个logs[i] [IDi, timei]表示ID为IDi的用户在timei分钟时执行了某个操作。 多个用户可以同时执行操作&#xff0c;单个用户可以在同一分钟内执行多个操作。指定…

Deno不只是个Javascript运行时

Deno 是一个安全的 JavaScript 和 TypeScript 运行时&#xff0c;作者是 Ryan Dahl&#xff08;也是 Node.js 的原作者&#xff09;。Deno 的诞生之初是为了解决 2009 年首次设计 Node.js 时的一些疏忽。我认为这种改造动机很有道理&#xff0c;因为我相信每个程序员都希望有机…

cmake跨平台构建工具

TOP目录 前言 CMake是一个跨平台的安装编译工具&#xff0c;可以用简单的语句来描述所有平台的安装(编译过程)。CMake可以说已经成为大部分C开源项目标配 因此&#xff0c;作为一名C C发开人员&#xff0c;看到cmake不应该一脸茫然… 作为初学者&#xff0c;通俗的认为cmake…

C语言入门(七)——结构体

复合类型与结构体 数据抽象 数据类型标志 嵌套结构体 复合类型与结构体 在编程语言中&#xff0c;最基本的&#xff0c;不可再分的数据类型称为基本类型&#xff0c;例如整型&#xff0c;浮点型;根据语法规则由基本类型组合而成的类型称为复合类型&#xff0c;例如字符串是…