用信号量实现互斥
Var mutex:semaphoer:=1;
Begin
Parbegin
Process1:begin //第一个进程
repeat
wait(mutex);
critical section
signal(mutex);
remainder section
until false;
end;
Process2:begin //第二个进程
repeat
wait(mutex); //申请资源
critical section //使用临界区
singal(mutex); //释放资源
remainder section //剩余区代码
until false;
end
Parend
注意
- 在实现互斥时,wait(mutex)和singal(mutex)必须成对地出现
- 缺wait(mutex)将会引起系统混乱,不能保证对临界资源的互斥访问
- 缺singal(mutex)将会使该临界资源永久不会被释放
经典的同步问题
- 生产者——消费者问题
- 读者——写者问题
- 哲学家进餐问题
生产者——消费者问题
一组生产者进程生产产品给一组消费者进程消费。为使他们并发执行,设一个有n个缓冲区的缓冲池,生产者一次向一个缓冲区中投入消息,消费者从一个缓冲区中取得消息。生产者——消费者问题实际上是相互合作进程关系的一种抽象。
例子
- 在输入时,输入进程是生产者,计算进程是消费者
- 在输出时,计算进程是生产者,打印进程是消费者
制约关系
- 不允许消费者进程到一个空缓冲区中取产品
- 不允许生产者进程到一个已满且还没被取走的缓冲区中投放产品
用记录型信号量解决生产者——消费者问题
- 设有n个缓冲区,每个缓冲区存放一个消息,用互斥信号量mutex对缓冲池实现互斥访问
- 利用资源信号量empty和full分别表示缓冲池中空缓冲区及满缓冲区的数量,又假定这些生产者和消费者相互等效,只要缓冲池未满,生产者便可将消息送入缓冲池;只要缓冲池未空,消费者便可从缓冲池取走一个消息。
var mutex:semaphore:=1;
empty:semaphore:=n;
full:semaphore:=0;
buffer:array[0,1,……,n-1] of item; //生产者生产出来的一个数据就是item
in,out:integer:=0,0; //in记录放入数据的地址,out记录取出数据的地址,其实就是buffer下标
生产者进程:
Procedure:begin
repeat
……
procedure an item nextp; //生产一个数据(下一个)
……
wait(empty); //申请一个空缓冲区,申请成功,empty信号量减1
wait(mutex);
Buffer(in):=nextp; //将nextp放入下标是in的缓冲区中
in:=(in+1) mod n;
singal(mutex); //释放缓冲区
singal(full); //将full信号量加1
until false;
end;
消费者进程
consumer:begin
repeat
wait(full); //申请一个缓冲区
wait(mutex); //含义是判断当前有没有生产者在使用申请的缓冲区
nextc:=Buffer(out);
out:=(out+1) mod n;
singal(mutex);
singal(empty); //释放一个空缓冲区,empty加1
Consumer the item in nextc;
until false;
end;
注意
- 每个程序中互斥的wait(mutex)和singal(mutex)必须成对出现。
- 对资源信号量empty和full的P、V操作成对出现,但它们分别处于不同的程序中。例如P在计算进程中,而V在打印进程中,计算进程若因执行P而阻塞,则以后将由打印进程将它唤醒。
- 每个程序中的P操作顺序不能颠倒。应先执行对资源信号量的P操作,然后再执行对互斥信号量的P操作,否则可能引起进程死锁。
- V操作的顺序无所谓,都可以。