进程相互作用之信号量PV操作及其代码实现
信号量PV操作
基本介绍
- 信号量(Semaphore):是表示资源的实体,是一个与队列有关的整型变量,其值仅能由P、V操作改变。
- 信号量分为:公用信号量和私用信号量。
- 公用信号量:用于实现进程间的互斥,初值通常设为1,它所联系的一组并发进程均可对它实施P、V操作;
- 私用信号量:用于实现进程间的同步,初始值通常设为0或n,允许拥有它的进程对其实施Р操作。
数据结构
信号量的数据结构:
struct semaphore{
int value; //系统中的资源数
pointer_PCB queue; //阻塞进程队列
};//PCB表示进程控制块
//声明
semaphore s;
PV操作
P(s){//申请资源
if(--s.value<0){
该进程设置为阻塞态
将该进程的PCB插入阻塞队列s.queue末尾
}
}
V(s){//释放资源
if(++s.value <= 0){
唤醒相应阻塞队列s.queue中等待的一个进程
改变其状态为就绪态
并将其插入就绪队列
}
}

s. value >= 0时,其值表示还有可用的资源数;
s. value < 0时,其绝对值表示有多少个进程因申请该信号量表示的资源,得不到而进入阻塞态;


解决进程互斥问题

把P1-P3进程的互斥操作都包括在一个PV操作对中
由P2进入

举例1:


启发:写并发进程的时候需要明确互斥区
- 不同进程未进入互斥区时可以并发
- 不同进程进入互斥区时要用PV操作控制
解决进程同步问题
在同步问题中信号量的value值相比于“资源”资源来说,理解为“权限”会更合适,在一个同步问题中,一个进程的执行权限是由它的前驱进程赋予的



代码实现(以同步问题为例)
为了便于实现,将程序的运行操作也封装到PV操作中,即
- 如果P操作为信号量申请到权限,那么直接执行信号量所对应的进程
- 如果V操作赋予了信号量权限且信号量的阻塞队列中有进程,那么直接执行阻塞队列中的进程

代码如下:【本人才疏学浅,如有不足恳请斧正】
#include<iostream>
#include<string>
#include<queue>
using namespace std;
/*定义类:process表示一个进程*/
class process{
public :
/*构造函数*/
process() = default;
process(const string &name) : process_name(name){}
process(const process &p) :
process_name(p.process_name){}
/*成员函数*/
//执行进程
void _on(){cout<<process_name+": on"<<endl;}
//关闭进程
void _off() {cout<<process_name+": of"<<endl;}
//进程名
string process_name;
};
/*定义类:semaphore表示信号量*/
/*一个信号量控制一个进程*/
class semaphore{
/*友元声明:确保PV操作可以访问semaphore私有成员*/
friend void P(semaphore &s);
friend void V(semaphore &s);
public:
/*构造函数:参数为信号量控制的进程*/
semaphore(const process &p) :
present(p){};
private :
int value = 0; //同步问题value初始化为0
process present; //该信号量控制的进程
queue<process> blocked_processes; //阻塞队列
};
/*P操作:申请资源(权限)*/
void P(semaphore &s){
--s.value;//申请
if(s.value<0){//无资源(权限):进程进入阻塞队列
//打印提示信息
cout<<s.present.process_name+" is blocked"<<endl;
//将进程加入阻塞队列
s.blocked_processes.push(s.present);
}
else{//有资源:直接执行
s.present._on();
}
}
/*V操作:返回资源(给予权限)*/
void V(semaphore &s){
++s.value;//赋予
if(s.value>=0){//如果阻塞队列有进程:唤醒阻塞进程
if(!s.blocked_processes.empty()){
s.blocked_processes.front()._on();
s.blocked_processes.pop();
}
}
//否则什么也不做
}
//开车进程
process speed_up("speed_up");
//开门进程
process open_door("open_door");
//用两个信号量分别控制开车进程和开门进程
semaphore OpenDoor(open_door), Speed_Up(speed_up);
int main(){
V(OpenDoor); //赋予开车门的权限
P(OpenDoor); //申请权限:有权限,可以开,打印open_door: on
P(OpenDoor); //申请权限:无权限,开不了门,进入开门阻塞队列
P(Speed_Up); //申请权限:无权限,开不了车,进入开车阻塞队列
V(Speed_Up); //赋予权限:执行开车阻塞队列进程,打印speed_up: on
V(OpenDoor); //赋予权限:执行开门阻塞队列进程,打印open_door: on
return 0;
}
运行结果:

进程相互作用之信号量PV操作及其代码实现的更多相关文章
- Linux下IPC中的信号量PV操作
代码如下所示,两边对照查看程序!(左图为先运行进程 右图为后运行进程) 运行的效果就是:当左边的进程检测到EOF,释放资源V操作之后,右边的进程会迅速的执行对应的printf的操作! 所有代码文 ...
- linux下的信号量PV操作进阶之路
一.同步和互斥机制 信号量 互斥锁 同步:指多个任务按照约定的先后次序相互配合来完成一件事情. 比如读线程等待写线程写完之后再去读. 二.信号量-P/V操作 P(s)含义: if(信号量>0) ...
- java信号量PV操作 解决生产者-消费者问题
package test1; /** * 该例子演示生产者和消费者的问题(设只有一个缓存空间.一个消费者和一个生产者) * MySystem类定义了缓冲区个数以及信号量 * @author HYY * ...
- Operating System-进程/线程内部通信-信号量和PV操作
本文介绍操作系统进程管理的两个核心概念: 信号量 PV操作 一.信号量介绍 1.1 信号量引入 信号量(Semaphore)1965年由Dijkstra引入的.信号量一般由一个值是一个变量,其值有可能 ...
- 信号量与PV操作
在计算机操作系统中,PV操作是进程管理中的难点.首先应弄清PV操作的含义:PV操作由P操作原语和V操作原语组成(原语是不可中断的过程),对信号量进行操作,具体定义如下: P(S):①将信号量S的 ...
- Pintos修改优先级捐赠、嵌套捐赠、锁的获得与释放、信号量及PV操作
Pintos修改优先级捐赠.嵌套捐赠.锁的获得与释放.信号量及PV操作 原有的优先级更改的情况下面没有考虑到捐赠的情况,仅仅只是改变更改了当前线程的优先级,更别说恢复原本优先级了,所以不能通过任何有关 ...
- 信号量和PV操作写出Bakery算法的同步程序
面包店烹制面包及蛋糕,由n个销售员卖出.当有顾客进店购买面包或蛋糕时,应先在取号机上取号,然后等待叫号,若有销售员空闲时便叫下一号,试用信号量和PV操作写出Bakery算法的同步程序. 设计要求 1) ...
- 转 信号量与PV操作
在计算机操作系统中,PV操作是进程管理中的难点.首先应弄清PV操作的含义:PV操作由P操作原语和V操作原语组成(原语是不可中断的过程),对信号量进行操作,具体定义如下: P(S):①将信号量S的 ...
- 【转】进程同步之信号量机制(pv操作)及三个经典同步问题
原文地址:http://blog.csdn.net/speedme/article/details/17597373 上篇博客中(进程同步之临界区域问题及Peterson算法),我们对临界区,临界资源 ...
- OS__信号量(semaphore)PV操作
信号量的概念 1.信号量的类型定义 信号量(semaphore)的数据结构为记录型数据结构一个值和一个指针,指针指向等待该信号量的下一个进程.信号量的值与相应资源的使用情况有关,在操作系统中,信号量用 ...
随机推荐
- 获取Windows个性化中自带的聚焦锁屏
想要保存登录屏幕(锁屏界面)的背景图片,可以通过以下脚本一键获取: @echo off setlocal enabledelayedexpansion :: Windows Spotlight 锁屏图 ...
- 代码随想录Day17
654.最大二叉树 给定一个不重复的整数数组 nums . 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值. 递归地在最大值 左边 的 子数组前缀 ...
- docker部署宝塔面板
环境准备: 系统 rocky:9.2 部署流程: 1.安装docker dnf -y install yum-utils yum-config-manager --add-repo http://mi ...
- tar 解压文件时提示 Ignoring unknown extended header keyword
在 Linux 上使用 tar 解压文件时出现下列提示: tar: Ignoring unknown extended header keyword 'LIBARCHIVE.xattr.com.app ...
- Linux 内核相关命令
Shell 命令: ipcs # 查看共享内存 dmesg # 显示内核消息 sudo dmesg -c # 清空内核消息 sudo mknod /dev/rwbuf c 60 0 sudo insm ...
- uni-app和vue及微信小程序的异同
uni-app和vue的区别1.目录不同 uni-app目录依赖原生小程序风格,比如分包的概念 vue中对不同的页面只需要在views文件夹中定义不同组件,然后配置路由跳转就行了,所有页面都是这样, ...
- JSP——简介-快速入门
JSP 简介 JSP 快速入门 <%@ page contentType="text/html;charset=UTF-8" language=&qu ...
- Windows系统无法打开‘’网络发现‘’功能
Windows10无法开启网络发现 解决办法: 1. services.msc 2. 开启 SSDP Discovery ,设置 启动类型为 自动 ,服务状态为 启动 Windows7 无法开启网络发 ...
- Linux运行脚本./XXXsh: line 1: $‘\r‘: command not found问题
Linux运行脚本./XXXsh: line 1: $'\r': command not found问题 在执行./xxx.sh命令时,系统报错: ./xxx.sh: line 1: $'\r': ...
- 将读取的.raw文件转换为tensor张量送入网络
# coding:utf-8 import numpy as np import torch # 首先确定原图片的基本信息:数据格式,行数列数,通道数 rows=886#图像的行数 cols=492# ...