同步和互斥——生产者和消费者进程版

本文详细介绍了同步和互斥的概念,通过生产者和消费者问题的三个不同版本(1个生产者1个消费者、1个生产者1个消费者共用m个缓冲区、多生产者多消费者共用m个缓冲区)进行分析。文章提供了使用信号量和共享内存实现的C语言代码,强调了同步与互斥的关系,并指出同步与互斥的顺序不影响死锁的发生。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、同步和互斥的概念

什么是同步?什么是互斥?

同步是一种时序关系。如规定了进程1处理完事情A后,进程2才能处理事情B,经典的同步问题是生产者和消费者间的同步.

互斥描述的是一种独占关系.如任一时刻,进城1和进程2中只能有一个写文件C.

有人说互斥是一种特殊的同步,同步是一种更为复杂的互斥关系(见" http//topic.youkuaiyun.com/t/20020711/17/867228.html"),但我不这么认为!

首先上面的言论是矛盾的,如果AB互相包含,那A只能等于B,而同步和互斥显然是不等的。从前面的描述可以看出,同步和互斥是你中有我,我中有你的关系。当然如果你要从更广义地角度来说互斥是一种特殊的同步,我也没办法,毕竟我们的程序正确运行的前提就是同步。

 

二、生产者和消费者的问题分析

生产者和消费者的解答网络上有多种线程版本,但却没看到进程版本,所以我就来填补这一“空白”了。PS:使用进程版本的另一个重要原因是,想顺便复习下共享内存。

我们使用信号量来同步,用一个整型数组来当缓冲区。很显然这两者都要能够在各生产者和消费者进程间全局可见,所以我们用共享内存来实现他们。

生产者和消费者问题从易到难有三种。

 

1.         一个生产者和一个消费者,公用一个缓冲区

解决办法,定义两个信号量。

empty:表示缓冲区是否为空,初值为1,生产者用它来判断缓冲区是否可写。

full:表示缓冲区是否为满,初值为0,消费者用它来判断缓冲区是否可读。

producer(生产者)的伪码:

while(1)

{

P(empty);

写缓冲区;

V(full);

}

consumer(消费者)的伪码:

while(1)

{

P(full);

写缓冲区;

V(empty);

}

 

2.   一个生产者和一个消费者,公用m个环形缓冲区

分析过程与第一种情况类似,直接看伪码。

producer(生产者)的伪码:

while(1)

{

P(empty); /* empty初值为m */

写第in个缓冲区; /* in用来指示当前的第一个可写的缓冲区的下标,初值设为0 */

in = (in+1)%m;

V(full);

}

consumer(消费者)的伪码:

while(1)

{

P(full); /* full初值为0 */

读第out个缓冲区; /* out用来指示当前的第一个可读的缓冲区的下标,初值设为0 */

out = (out+1)%m;

V(empty);

}

 

3.      一组生产者和一组消费者,公用m个环形缓冲区

相比第2种情况,我们所要做的是用两个互斥变量mutex_producermutex_consumer,来实现各生产者间、各消费者间互斥地访问某个缓冲区。

producer(生产者)的伪码:

while(1)

{

P(empty); /* empty初值为m */

P(mutex_producer);

写第in个缓冲区; /* in用来指示当前的第一个可写的缓冲区的下标,初值设为0 */

in = (in+1)%m;

V(mutex_producer);

V(full);

}

 

consumer(消费者)的伪码:

while(1)

{

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值