文章目录
- 哲学家进餐问题
- 1.利用结构型信号量解决哲学家进餐问题
- 解决方案1:每次最多允许四位哲学家就餐
- 2.利用AND型信号量解决哲学家进餐问题
- 生产者-消费者问题
- 1.利用结构型信号量解决生产者-----消费者问题
- 单缓冲区生产者-消费者问题
- 多缓冲区
- 2.利用AND型信号量解决生产者-----消费者问题
- 读者-写者问题
- 1.利用结构型信号量解决读者-----写者问题
- 2.利用信号量集机制解决读者-----写者问题
- 理发师问题
- 结构型信号量解决理发师问题
- 吸烟者问题
信号量的应用问题总结
哲学家进餐问题
五位哲学家围坐一张圆桌,桌子中央放有一盘面条,桌上放五根筷子,每位哲学家只能拿起与他相邻的两根筷子吃饭
哲学家的生活方式是交替地进行思考和进餐
1.利用结构型信号量解决哲学家进餐问题
数据结构:每根筷子都是一个临界资源,都应定义一个信号量,为五根筷子定义一个信号量数组,每个信号量的初值为1
semaphore chopstick[5];
for (int i=0;i<5;i++) chopstick[i]=1;
//操作描述:第i位哲学家的活动如下:
Process philosopher_i()
{
while(true)
{
thinking();
P(chopstick [ i ]);
P(chopstick [(i+1) mod 5]);
eating ;
V(chopstick [ i ]);
V(chopstick [(i+1)mod 5]);
thinking() ;
}
}
算法分析:
若每个哲学家都各自拿起他左边的一根筷子,然后再去拿他右边的筷子时,将都拿不到右边的筷子,大家又都不会放下手中的筷子,大家在相互等待别人释放筷子,系统于是进入死锁状态
解决方案1:每次最多允许四位哲学家就餐
semaphore chopstick[5], s=4;
for (int i=0;i<5;i++) chopstick[i]=1;
process philosopher_i()
{
while(true)
{ thinking();
P(s);
P(chopstick[i]);
P(chopstick[(i+1) mod 5]);
eating ;
V(chopstick[i]);
V(chopstick[(i+1) mod 5]);
V(s);
thinking() ;
}
}
解决方案2:分奇偶号
奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子
偶数号哲学家先拿他右边的筷子,然后再去拿左边的筷子
解决方案3:仅当哲学家的左右两根筷子均可用时,才允许他拿起筷子进餐
2.利用AND型信号量解决哲学家进餐问题
Semaphore chopstick[5];
for (int i=0;i<5;i++) chopstick[i]=1;
cobegin
Process philosopher_i(){
while(true){
thinking ;
SP(chopstick[i],chopstick[(i+1)mod 5]);
eating ;
SV(chopstick[i],chopstick[(i+1) mod 5]);
}
}
coend
生产者-消费者问题
1.利用结构型信号量解决生产者-----消费者问题
数据结构:
含有n个缓冲区的公用缓冲池
互斥信号量mutex:实现诸进程对缓冲池的互斥使用,一次仅允许一个进程读或写公用缓冲池,初值为1
资源信号量empty:记录空缓冲区个数,初值为n
资源信号量full:记录满缓冲区个数,初值为0
操作要求:多个生产者进程之间、多个消费者进程之间、生产者进程与消费者进程之间均能正确同步
单缓冲区生产者-消费者问题
int B;
Semaphore empty, full;
empty=1;
full=0;
cobegin
process producer (){
while(true)
{
produce();
p(empty);
Append() to B;
V(full);
}
}
Process consumer()
{
while(true)
{
p(full);
take() from B;
v(empty);
consume();
}
}
coend
多缓冲区
对于m个生产者和n个消费者,它们共享可存放k件产品的缓冲区
为了使其协调工作,必须使用一个信号量mutex,限制生产者和消费者互斥地对缓冲区进行存取
另用两个信号量empty和full,以保证生产者不向已满的缓冲区中放入产品,消费者不从空缓冲区中取产品
item B[k];
Semaphore empty, full, mutex;
empty=k;full=0;mutex=1;
cobegin
process producer_i (){
while(true)
{
produce();
p(empty);
p(mutex);
append to B[in];
in= (in+1)%k;
V(mutex);
V(full);
}
}
Process consumer_j()
{
while(true)
{
p(full);
P(mutex);
take() from B[out];
out=(out+1)%k;
v(mutex);
v(empty);
consume();
}
}
coend
2.利用AND型信号量解决生产者-----消费者问题
semaphore mutex , empty , full :
semaphore = 1 , n , 0 ;
item buffer [n];
int in , out= 0 , 0 ;
begin
parbegin
producer :
begin
while(true)
{
produce an item in nextp ;
SP(empty,mutex);
Buffer(in)= nextp ;
in =(in+1) mod n ;
SV(mutex,full);
}
end
consumer :
begin
while(true)
{
SP(full,mutex);
nextc = buffer(out);
out =(out + 1) mod n ;
SV(mutex,empty);
}
end
parend
end
读者-写者问题
若干Reader进程和Writer进程共享一个数据文件,允许多个Reader进程同时读一个共享对象,但不允许一个Writer进程与其它Reader进程或Writer进程同时访问共享对象
情况分析: 如果读者数目ReadCount为0,则可能有也可能没有写者在写
如果读者数目ReadCount不为0,则不会有写者在写,请求读的读者便可读
如果读者数目ReadCount为0,又没有写者在写,则请求写的写者才能写
1.利用结构型信号量解决读者-----写者问题
数据结构:
互斥信号量mutex:用于Reader与Writer、Writer与Writer之间的互斥,初值为1;
ReadCount:正在读的进程数目,初值为0
互斥信号量 rmutex:用于Reader与Reader 互斥访问整型量ReadCount,初值为1
semaphore rmutex , mutex = 1 , 1 ;
int ReadCount = 0;
parbegin
Reader:
{
P(rmutex);
if (ReadCount==0) then P(mutex);
ReadCount = ReadCount + 1 ;
V(rmutex);
read ;
P(rmutex);
ReadCount= ReadCount - 1 ;
if (ReadCount==0) then V(mutex);
V(rmutex);
}
Writer
{
P(mutex);
write ;
V(mutex);
}
parend
2.利用信号量集机制解决读者-----写者问题
要求 :规定最多允许RN个读者同时读
数据结构:
读者数目信号量L ,初值为RN;
信号量mx,表示有无写者在写,初值为1
int RN;
semaphore L , mx = RN , 1 ;
parbegin
Reader
{
SP(L , 1 , 1 );
SP(mx, 1 , 0);
read ;
SV( L , 1);
}
writer
{
SP(mx , 1 , 1 ; L , RN , 0);
write ;
SV(mx , 1);
}
parend
理发师问题
理发店有一位理发师、一把理发椅和n把供等候理发的顾客坐的椅子 如果没有顾客,理发师便在理发椅上睡觉 当一个顾客到来时,它必须叫醒理发师
如果理发师正在理发时又有顾客来到,则如果有空椅子可坐,他们就坐下来等待,否则就离开
结构型信号量解决理发师问题
int waiting=0; //等候理发的顾客数
int CHAIRS=0; //为顾客准备的椅子数
semaphore customers, barbers, mutex;
customers = 0; barbers= 0; mutex= 1;
Procedure barber;
{
Whlie(1)
{
P(customers); //若无顾客,理发师睡眠
P(mutex); //进程互斥
waiting = waiting – 1; //等候顾客数少一个
V(barbers); //理发师去为一个顾客理发
V(mutex); //开放临界区
cut-hair( ); //正在理发
}
}
procedure customer
{
P(mutex); //进程互斥
if (waiting<CHAIRS) //看看有没有空椅子
{
waiting = waiting+1; //等候顾客数加1
V(customers); //必要的话唤醒理发师
V(mutex); //开放临界区
P(barbers); //无理发师, 顾客坐着养神
get_haircut();
}
else V(mutex); //人满了,走吧!
}
吸烟者问题
三名吸烟者在同一个房间内,还有一位香烟供应者,为了制造并抽掉香烟,每位吸烟者需要拥有三样东西:烟草、纸和火柴,供应者有丰富的货物提供。三位吸烟者中,第一个人有自己的烟草,第二个人有自己的纸,第三个人有自己的火柴,供应者随机地将两样东西放在桌子上,允许一位吸烟者进行对健康不利的吸烟,当吸烟者完成吸烟后唤醒供应者,供应者再把两样东西放在桌子上,唤醒另一位吸烟者。试采用信号量和PV操作编写他们同步工作的程序
semaphore S = 1,S1 = 0, S2 = 0,S3 = 0;
bool flag1,flag2,flag3; /*flage1、flage2、flage3代表烟草、纸、火柴*/
process 供应者( )
{
while(true) {
P(S);
//随机生成整数random
if(random%3=0) V(S1); /*供纸和火柴*/
else if(random%3=1) V(S2); /*供烟草和火柴*/
else V(S3); /*供烟草和纸*/
}
}
Process Smoker1()
{
P(S1);
制造香烟
吸烟;
V(S);
}
Process Smoker2()
{
P(S2);
制造香烟
吸烟;
V(S);
}
Process Smoker3()
{
P(S3);
制造香烟
吸烟;
V(S);
}