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. 简介 进程间通讯的机 ...
随机推荐
- Pikachu漏洞练习平台实验——文件包含(File Inclusion)(六)
1.概述 1.1简介 在 Web 后台开发中,程序员往往为了提高效率以及让代码看起来更加简洁,会使用 “包含” 函数功能.比如把一系列功能函数都写进 function.php 中,之后当某个文件需要调 ...
- Stream的排序
1.list<Integer>的正序 List<Integer> list = new ArrayList<>();list.add(50);list.add(45 ...
- zabbix3.0自动发现磁盘并监控磁盘IO
Zabbix 版本:3.0 操作系统:Ubuntu16.04 操作环境,在被监控的主机上安装zabbix agent.安装方式为源码包安装. 简要安装步骤: 参考:https://www.zabbix ...
- Activiti6.0 java项目框架 spring5 SSM 工作流引擎 审批流程
工作流模块----------------------------------------------------------------------------------------------- ...
- JSON —— 数据结构
1.什么是 JSON JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写 JSON 采用完全独立于语言的文本格式,但是也使用了类似于 C ...
- CSS-03 queue方法
queue方法 摘自W3C school手册,用于简单理解使用queue方法 队列 每个元素均可拥有一到多个由 jQuery 添加的函数队列.在大多数应用程序中,只使用一个队列(名为 fx).队列运行 ...
- elasticsearch 基础 —— Update API
Update API 更新API允许基于提供的脚本更新文档.该操作从索引获取文档(与分片并置),运行脚本(使用可选的脚本语言和参数),并对结果进行索引(也允许删除或忽略操作).它使用版本控制来确保在& ...
- css day1
基础知识 css:层叠样式表 以html为基础,提供丰富的功能,如字体.颜色.背景的控制及整体排版 css中只有(冒号): 没有(等于号)= css样式规则 1.选择器用于指定css样式作用的htm ...
- MySQL--11 备份的原因
目录 一.备份的原因 二.备份的类型 三.备份的方式 四.备份策略 五.备份工具 六.企业故障恢复案例 1.模拟环境 2.模拟恢复数据过程: 一.备份的原因 运维工作的核心简单概括就两件事: 1)第一 ...
- 【LeetCode】队列 queue(共8题)
[346]Moving Average from Data Stream [353]Design Snake Game [363]Max Sum of Rectangle No Larger Than ...