信号量机制

信号量机制

有多少资源就把信号量初值设为多少。申请资源时进行P操作,释放资源时进行V操作。

实现进程互斥

步骤:
1.分析并发进程的关键活动,划定临界区
2.设置互斥信号量mutex,初值为1(一般为临界资源数目)
3.在临界区之前执行P(mutex)
4.在临界区之后执行V(mutex)

/*信号量机制实现互斥*/
P1(){
	...
	P(mutex);	//使用临界资源前需要加锁
	临界区的代码块...
	V(mutex);	//使用临界资源后需要解锁
}

P2(){
	...
	P(mutex);	//使用临界资源前需要加锁
	临界区的代码块...
	V(mutex);	//使用临界资源后需要解锁
}

注:对不同的临界资源需要设置不同的互斥信号量。
P、V操作必须成对出现。

实现进程同步

1.分析什么地方需要实现“同步关系”,即要保证“一前一后”执行两个操作
2.设置同步信号量S,初始值为0
3. 在“前操作”之后执行V(S)
4. 在“后操作”之前执行P(S)

解题步骤:1.确定进程的个数及每个进程的工作
2.确定关键工作步(需要控制的)
3.确定信号量表示的含义:当信号量的值为0时,表示期望的消息尚未产生;当信号量的值非0时,表示期望的消息已经存在
4.写出伪代码。在同步关系的控制中同一信号量的P(Wait)、V(signal)操作成对出现,但它们分别在不同的进程中。

/*保证,代码4一定是在代码2之后执行*/
semaphore S=0;	//初始化同步信号量,初始值为0
P1(){
	代码1;
	代码2;
	V(S);
	代码3;
}
P2(){
	P(S)
	代码1;
	代码2;
	代码3;
}

若先执行到V(S)操作,则S++后S=1.之后当执行到P(S)操作时,由于S=1,表示有可用资源,会执行S–,S的值变回0,P2进程不会执行block原语,而是继续往下执行代码4.
若先执行到P(S)操作,由于S=0,S–后S=-1,表示此时没有可用资源,因此P操作中会执行block原语,主动请求阻塞。之后当执行完代码2,继而执行V(S)操作,S++,使S变回0,由于此时有进程在该信号量对应的阻塞队列中,因此会在V操作中执行wakeup原语,唤醒P2进程。这样P2就可以继续执行代码4了。

例:
假设有三个并发进程P、Q、R,其中P负责从输入设备读取信息并传送给Q,Q将信息加工后传送给R,R则负责将信息打印输出。进程P、Q共享一个缓冲区,进程Q、R共享另一个缓冲区。


3个进程P、Q、R
P进程:
从输入设备上读入信息
将信息放入缓冲区1
Q进程:
从缓冲区1中取出信息
将信息放入缓冲区2中
R进程:
从缓冲区2取出信息
将信息打印输出

确定同步、互斥关系
-同步:P当缓冲区1中无数据时,才可以向缓冲区1写入信息
-同步:Q当缓冲区1中有数据时,才可以向缓冲区1读取信息
-同步:Q当缓冲区2中无数据时,才可以向缓冲区2写入数据
-同步:R当缓冲区2中有数据时,才可以向缓冲区2读取数据

设置信号量:
-缓存区1中无数据,empty1,初值1
-缓存区1中有数据,full1,初值0
-缓存区2中无数据,empty2,初值1
-缓存区2中有数据,full2,初值0

process P(){
while (1){
从输入设备上读取数据;
P(empty 1);
将信息放入缓冲区1;
V(full1);
}
}

生产者-消费者问题

系统中有一组生产者进程和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。(注:这里的“产品”可理解为某种数据)
生产者、消费者共享一个初始为空、大小为n的缓冲区。
只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。(同步关系)
只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。(同步关系)
缓冲区时临界资源,各进程必须互斥访问。(互斥关系)

刚开始空闲缓冲区的数量为n,非空缓冲区的数量为0

生产者每次要消耗§一个空闲缓冲区,并生产(V)一个产品。
消费者每次要消耗§一个产品,并释放一个空闲缓冲区(V)。
向缓冲区放入/取走产品需要互斥。

semaphore mutex = 1;	//互斥信号量,实现对缓冲区的互斥访问
semaphore empty= n;		//同步信号量,表示空闲缓冲区的数量
semaphore full= 0;		//同步信号量,表示产品的数量,也即非空缓冲区的数量
producer(){
	while(1){
		生产一个产品;
		P(empty);		//消耗一个空闲缓冲区
		P(mutex);		//实现互斥是在同一进程中进行一对PV操作
		把产品放入缓冲区;
		V(mutex);
		V(full);		//增加一个产品
	}
}
consumer(){
	while(1){
		P(full);			//消耗一个产品(非空缓冲区)
		P(mutex);
		从缓冲区取出一个产品;
		V(empty);			//增加一个空闲缓冲区
		V(empty);
		使用产品;
	}
}

例:
有一个阅览室,共有100个座位。读者进入阅览室时必须在入口处进行登记;离开阅览室时必须进行注销。使用PV操作描述读者进入/离开阅览室的同步与互斥关系。

Reader进程{
	登记
	进入阅览室
	读书
	离开阅览室
	注销
}

分析:在入口、出口处读者应该互斥进行登记和注销;100个座位,100个互斥资源

设置信号量:
-阅览室内的座位数量,seat,初值100
-入口处进行登记设置互斥信号量Sin,初值1,表示当前可用

begin
	Sin,Sout,seat:semaphore;
	seat := 1;
	Sout := 1;
cobegin
	process Reader-i(i = 1,2,...,n);
	begin
		P(seat);
		P(Sin);
		登记;
		V(Sin);
		进入阅览室;
		读书;
		离开阅览室;
		P(Sout);
		注销;
		V(Sout);
		V(seat);
	end
coend;
end;

PV操作题目分析步骤:
1.关系分析。找出题目中描述的各个进程,分析他们之间的同步、互斥关系
2.整理思路。根据各进程的操作流程确定P、V操作的大致顺序。
3.设置信号量。设置需要的信号量,并根据题目条件确定信号量初值。(互斥信号量初值一般为1,同步信号量的初值要看对应资源的初始值是多少)

进程互斥解题步骤:
1.确定临界资源的个数
2.确定进程的关键工作步(使用到临界资源)
3.确定信号量的初值(临界资源的个数)
4.写出伪代码

实现互斥的P操作一定要在实现同步的P操作之后
V操作不会导致进程阻塞,因此两个V操作顺序可以交换
前V后P

P操作:进入临界区前
V操作:离开临界区后

多生产者-多消费者问题

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值