Classic IPC Problems 经典的进程间通信问题
The Producer-Consumer Problem
Presenter Notes:
生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。
代码:
#define N 100 /* number of slots in the buffer */
semaphore mutex = ; /* controls access to critical region*/
semaphore empty = N; /* counts empty buffer slots */
semaphore full = ; /* counts full buffer slots */ void producer(void) {
int item;
while (TRUE) {
item = produce_item();
P(empty);
P(mutex);
insert_item(item);
V(mutex);
V(full);
}
}
void consumer(void) {
int item;
while (TRUE) {
P(full);
P(mutex);
item = remove_item();
V(mutex);
V(empty);
consume_item(item);
}
}
Dining Philosophers Problem
Presenter Notes:
哲学家就餐问题是在计算机科学中的一个经典问题,用来演示在并行计算中多线程同步(Synchronization)时产生的问题。在1971年,著名的计算机科学家艾兹格·迪科斯彻提出了一个同步问题,即假设有五台计算机都试图访问五份共享的磁带驱动器。稍后,这个问题被托尼·霍尔重新表述为哲学家就餐问题。这个问题可以用来解释死锁和资源耗尽。
哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。哲学家就餐问题有时也用米饭和筷子而不是意大利面和餐叉来描述,因为很明显,吃米饭必须用两根筷子。 哲学家从来不交谈,这就很危险,可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。即使没有死锁,也有可能发生资源耗尽。例如,假设规定当哲学家等待另一只餐叉超过五分钟后就放下自己手里的那一只餐叉,并且再等五分钟后进行下一次尝试。这个策略消除了死锁(系统总会进入到下一个状态),但仍然有可能发生“活锁”。如果五位哲学家在完全相同的时刻进入餐厅,并同时拿起左边的餐叉,那么这些哲学家就会等待五分钟,同时放下手中的餐叉,再等五分钟,又同时拿起这些餐叉。
#define N 5
#define LEFT (i+N-1)%N
#define RIGHT (i+1)%N
#define THINKING 0
#define HUNGRY 1
#define EATTING 2
int state[N]; /* array to keep track of everyone's state */
semaphore mutex=; /* mutual exclusion for critical regions */
semaphore s[N]; /* one semaphore per philosopher */ void philosopher(int i)
{
while (TRUE) {
think(i);
take_forks(i);
eat();
put_forks(i);
}
}
void take_forks(int i)
{
P(mutex)
state[i] = HUNGRY;
test(i);
V(mutex);
P(s[i]);
} void put_forks(int i)
{
P(mutex)
state[i] = THINKING;
test(LEFT);
test(RIGHT);
V(mutex);
}
void test(int i)
{
if( state[i] == HUNGRY
&& state[LEFT] != EATTING
&& state[RIGTH] != EATTING) {
state[i] = EATTING;
V(s[i]);
}
}
The Readers and Writers Problem
Presenter Notes:
有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:
①允许多个读者可以同时对文件执行读操作;
②只允许一个写者往文件中写信息;
③任一写者在完成写操作之前不允许其他读者或写者工作;
④写者执行写操作前,应让已有的读者和写者全部退出。
分析思想:
读者到: 1)无读者、写者,新读者可以读
2)有写者等,但有其它读者正在读,则新读者也可以读
3)有写者写,新读者等
写者到: 1)无读者,新写者可以写
2)有读者,新写者等待
3)有其它写者,新写者等待。
Reader priority solution
semaphore fmutex= //fmutex --> access to file;
sepaphore rdcntmutex=; // rdcntmutex --> access to reader_count
int reader_count = ; // reader_count --> the number of readers void reader(){
while ( TRUE ){
P(rdcntmutex);
if( reader_count == ) { P(fmutex); }
reader_count = reader_count + ;
V(rdcntmutex);
//Do read operation ...
P(rdcntmutex);
reader_count = reader_count - ;
if( reader_count == ) { V(fmutex); }
V(rdcntmutex);
}
}
void writer(){
while ( TRUE ){
P(fmutex);
//Do write operation ...
V(fmutex);
}
}
Writer priority solution
semaphore fmutex=, rdcntmutex=, wtcntmutex=, queue=;
int reader_count = , writer_count = ; void reader(){
while( TRUE ){
P(queue);
P(rdcntmutex);
if( reader_count == ) { P(fmutex); }
reader_count = reader_count + ;
V(rdcntmutex);
V(queue);
//Do read operation ...
P(rdcntmutex);
reader_count = reader_count - ;
if( reader_count == ) { V(fmutex); }
V(rdcntmutex);
}
}
void writer(){
while( TRUE ){
P(wtcntmutex);
if( writer_count == ) { P(queue); }
writer_count = writer_count + ;
V(wtcntmutex);
P(fmutex);
//Do write operation ...
V(fmutex);
P(wtcntmutex);
writer_count = writer_count - ;
if( writer_count == ) { V(queue); }
V(wtcntmutex);
}
}
Fair competition solution
void reader() {
// ... same as reader() in "writer priority solution" ...
} void writer(){
while( TRUE ){
P(queue);
P(fmutex);
V(queue);
//Do write operation ...
V(fmutex);
}
}
The sleeping barber problem
Presenter Notes:
假设有一个理发店只有一个理发师,一张理发时坐的椅子,若干张普通椅子顾客供等候时坐。没有顾客时,理发师就坐在理发的椅子上睡觉。顾客一到,他不是叫醒理发师,就是离开。如果理发师没有睡觉,而在为别人理发,他就会坐下来等候。如果所有的椅子都坐满了人,最后来的顾客就会离开。 在出现竞争的情况下问题就来了,这和其它的排队问题是一样的。实际上,与哲学家就餐问题是一样的。如果没有适当的解决方案,就会导致进程之间的“饿肚子”和“死锁”。 如理发师在等一位顾客,顾客在等理发师,进而造成死锁。另外,有的顾客可能也不愿按顺序等候,会让一些在等待的顾客永远都不能理发。
代码:
#define CHAIRS 5 /* # chairs for waiting customers */
semaphore customers = ; /* # of customers waiting for service */
semaphore barbers = ; /* # of barbers waiting for customers */
semaphore mutex = ; /* for mutual exclusion */
int waiting = ; /* customers are waiting (not being cut) */ void barber(void)
{
white (TRUE) {
P(customers); /* go to sleep if # of customers is 0 */
P(mutex); /* acquire access to 'waiting' */
waiting = waiting − ; /* decrement count of waiting customers */
V(barbers); /* one barber is now ready to cut hair */
V(mutex); /* release 'waiting' */
cut_hair(); /* cut hair (outside critical region) */
}
}
void customer(void)
{
P(mutex); /* enter critical region */
if (waiting < CHAIRS) { /* if there are no free chairs, leave */
waiting = waiting + ; /* increment count of waiting customers */
V(customers); /* wake up barber if necessary */
V(mutex); /* release access to 'waiting' */
P(barbers); /* go to sleep if # of free barbers is 0 */
get_haircut(); /* be seated and be serviced */
} else {
V(mutex); /* shop is full; do not wait */
}
}
Classic IPC Problems 经典的进程间通信问题的更多相关文章
- 进程间通信的两种实现方式(IPC)
进程间通信的两种实现方式(IPC) IPC: iter processing communicate 进程间通信:IPC(iter process communicate)linux free-m 可 ...
- 微服务的进程间通信(IPC)
微服务的进程间通信(IPC) 目录 微服务的进程间通信(IPC) 术语 概述 通信视角 APIs 消息格式 RPC REST gRPC 断路器 API通信的健壮性 服务发现 异步消息 概念 消息 消息 ...
- Linux进程间通信(System V) --- 共享内存
共享内存 IPC 原理 共享内存进程间通信机制主要用于实现进程间大量的数据传输,下图所示为进程间使用共享内存实现大量数据传输的示意图: 共享内存是在内存中单独开辟的一段内存空间,这段内存空间有自己特有 ...
- 网络硬盘录像机和数字硬盘录像机区别(nvr dvr ipc区别)
DVR Digital Video Recorder 数字硬盘录像机 NVR Network Video Recorder 网络硬盘录像机 DVR(数字硬盘录像机)和NVR(网络硬盘录像机)在 ...
- POSIX 进程间通信 (可移植操作系统接口)
1.什么是POSIX标准 Portable Operating System Interface for Computing System. 他是一个针对操作系统(准确地说是针对类Unix操作系统)的 ...
- android IPC通信(上)-sharedUserId&&Messenger
看了一本书,上面有一章解说了IPC(Inter-Process Communication,进程间通信)通信.决定结合曾经的一篇博客android 两个应用之间的通信与调用和自己的理解来好好整理总结一 ...
- 守护进程,互斥锁,IPC,生产者与消费者模型
守护进程: b 进程守护 a进程,当a进程执行完毕时,b进程会跟着立马结束 守护进程用途: 如果父进程结束了,子进程无需运行了,就可以将子进程设置为父进程的守护进程 例如我们qq视频聊天时,当我们退出 ...
- IPC机制1
1.Android IPC简介 Inter-Process Communication的缩写就是IPC,含义是进程间通信或是跨进程间通信,是指两个进程进行交换数据的过程. 进程是什么? 进程在pc上就 ...
- Linux ns 5. IPC Namespace 详解
文章目录 1. 简介 2. 源码分析 2.1 copy_ipcs() 2.2 ipcget() 2.3 ipc_check_perms() 2.4 相关系统调用 参考文档: 1. 简介 进程间通讯的机 ...
随机推荐
- 线段树(two value)与树状数组(RMQ算法st表)
士兵杀敌(三) 时间限制:2000 ms | 内存限制:65535 KB 难度:5 描述 南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比 ...
- Pandas处理缺失的数据
处理丢失数据 有两种丢失数据: None np.nan(NaN) import numpy as np import pandas from pandas import DataFrame 1. No ...
- git-ssh-keygen
ssh-keygen 先看本地是否已经有了密钥 cd ~/.ssh 该文件夹下会包含两个文件 id_rsa --私钥 id_rsa.pub --公钥 如果没有这两个文件的话就需要重新生成(有的话使用一 ...
- console.log的高级用法
//基本用法 console.log('最常见用法\n换行'); console.error('输出错误信息 会以红色显示'); console.warn('打印警告信息 会以黄色显示'); cons ...
- 115-基于TI TMS320DM6467T Camera Link 机器视觉 智能图像分析平台
基于TI TMS320DM6467无操作系统Camera Link智能图像分析平台 1.板卡概述 该板卡是我公司推出的一款具有超高可靠性.效率最大化.无操作系统的智能视频处理卡,是机器视觉开发上的首选 ...
- 11-基于CPCI的中频功率放大收发板
1.板卡参数介绍 无线输入口 无线发射口 1M~3GHZ,可调,步进100HZ(非跳频模式) 功率:≤﹢10±2.5 dBm 收发通道数 收发各1通道/板 中频输入输出 70MHz, 5MHz/30M ...
- Linux就该这么学09学习笔记
参考链接:https://www.linuxprobe.com/chapter-09.html 配置网卡服务 配置网卡参数 1.执行nmtui命令运行网络配置工具 2.选中Edit a connect ...
- django报错
报错: SyntaxError Generator expression must be parenthesized 问题原因: 由于django 1.11版本和python3.7版本不兼容, 2.0 ...
- 《Redis深度历险:核心原理和应用实践》学习笔记一
1.redis五种数据结构 1.1 String字符串类型,对应java字符串类型 用户信息序列化后,可以用string类型存入redis中批量读写string类型,见效网络消耗数字类型的string ...
- elasticsearch 进行聚合+去重查询
转载:https://www.jianshu.com/p/c03c3c8bf583 以客户customer为例 我想查询每日的客户数. 先按照日期分桶,然后在桶内按照 姓名来去重 来计算客户数(实际会 ...