生产者-消费者(合作关系)
不能生产者在生产的时候 消费者进行消费 反之也不行
如果仓库堆满了 生产者不能再进行生产
如果仓库空了 消费者不能再进行消费
记录型信号量写法
semaphore mutex=1;//实现互斥
semaphore empty=n;//空缓冲的数量
semaphore full=0;//满缓冲的数量
void producer(){
生产一个产品
P(empty); //判断是否有消费者在消费 判断empty>0嘛
P(mutex);
把产品放入缓冲区
V(mutex);
V(full);
}
void customer(){
P(full);
P(mutex);
从缓冲区中取出产品
V(mutex);
V(empty);
使用产品
}
AND型信号量写法
semaphore mutex=1;//实现互斥
semaphore empty=n;//空缓冲的数量
semaphore full=0;//满缓冲的数量
void producer(){
生产一个产品
Swait(empty,mutex)
把产品放入缓冲区
Ssignal(mutex,full)
}
void customer(){
Swait(full,mutex);
从缓冲区中取出产品
Ssignal(mutex,empty)
使用产品
管程写法
//N是公用缓冲池中具有N个缓冲区
Monitor Producerconsumer
{
/*变量说明*/ //成员变量
item buffer[N];
int in,out;//共享数据说明
condition notfull,notempty;//条件变量说明 //判断资源是否满或者空
int count; //缓冲池中已有的产品数目
public: //能被进程调用的过程
/*对数据结构操作的过程*/ //成员函数
void put(item x)
{
if(count >= N)cwait(notfull);//如果缓冲池已满 该生产者进程需要挂起等待 并将该进程放进notfull阻塞队列中
//cwait(notfull)应该等价于notfull.wait()
buffer[in] = x;
in = (in+1)%N;
count++;
csignal(notempty);//此时count增加了 公共数据发生了改变(也就是这里不再是空的了 那些因为仓库空而被挂起无法消费的消费者进程重新启动) 重新启动一个被挂起的进程 这里面填notempty是因为要重启的是放在notempty阻塞队列里面的进程
}
void get(item x)
{
if(count <= 0)cwait(notempty);
x = buffer[out];
out = (out+1)%N;
count--;
csignal(notfull);
}
{in = 0;out = 0;count = 0;} //这里就是初始化数据
}PC;
void produce()//这个是一个进程
{
item x;
while(TRUE)
{
...
procdece an item in nextp;
PC.put(x); //直接调用PC管程
}
}
void consumer()
{
item x;
while(TRUE)
{
PC.get(x);
consume the item in nextx;
...
}
}
void main()
{
cobegin
producer();consumer();
coend
}
哲学家进餐问题(进程需要多个资源)
五个哲学家围坐在一张圆桌上 每个哲学家面前一个碗一只筷子 只有拿到两只筷子时才能进餐 进餐结束放下筷子
问题:如果让并发执行可能大家都只拿到一支筷子而死锁
解决办法:
1.最多只允许四个哲学家去拿筷子 这样一定会有人可以拿到两支筷子 然后释放资源
2.(AND型)仅当哲学家能拿到左右两支筷子时才能去拿筷子 要不然不能拿
3.让奇数号的哲学家先拿左边的筷子 再拿右边的筷子 让偶数号的哲学家先拿右边的筷子 再拿左边的筷子 (就是最开始相邻的两个人都竞争同一支筷子只有竞争拿到筷子的人才能拿另一只 否则就等待)
AND型信号量写法
semaphone chopstick[5] = {1,1,1,1,1};
do
{
...
Swait(chopstick[i+1%5],chopstick[i]);//[i+1%5]就是另一只筷子 并且数量不能超过5
.。。
SSignal(chopstick[i+1%5],chopstick[i]);
}while(TRUE);
读者-写者问题
允许同时多个读者读一本书 但是只允许一个写者写书 并且在读者和写者不能同时读写一本书
记录型信号量
semaphore wmutex = 1;
semaphore rmutex = 1;//rmutex是防止多个进程同时对readcount进行更改 引起混乱 比如如果没有wait(rmutex)和signal(rmutex)则假设有两个读者R1,R2 其中一个已经在读书 另一个刚来 执行顺序如下
/*
R1从readcount--开始 R2从if(readcount == 0)开始
此时 readcount = 1 wmutex = 0(因为R1进来时执行过wait(wmutex);)
R1 readcout-- //readcout = 0
R2 if(readcount == 0) //通过
R2 wait(wmutex) //wmutex = -1
R2 readcount++ //readcount = 1
R1 if(readcount == 0)//不通过
。。。
直到R2 signal(wmutex) //wmutex = 0
此时就出现了问题 因为此时没有读者在读书 但是wmutex = 0(应该是1的) 写者也进不去
*/
int readcount = 0;
void reader()
{
do{
wait(rmutex);//防止多读者readcount写入
if(readcount == 0)wait(wmutex);//如果在该读者来之前没人在读书 则让wmutex为0 不让写者通过
readcount++;//读者数量+1
signal(rmutex);//写入完毕 其他读者可以写入readcount
...
perform read operation;
...
wait(rmutex);//同样效果 要对readcout写入
readcount--;//读者离开 数量-1
if(readcount == 0)signal(wmutex);//如果该读者是最后一个读者 则该读者离开之后 就没有人读书了 那么写者可以通过 让wmutex = 1
signal(rmutex);
}while(TRUE);
}
void Writer()
{
do
{
wait(wmutex);//判断是否有读者在内 没有则可以通过
perform weite operation;
signal(wmutex);
}while(TRUE);
}
void main()
{
cobegin
Reader();Writer();
coend
}