/**************************************************************************************************
** 吸烟者问题
** 问题描述:
** 三个吸烟者进程和一个经销商进程,每个吸烟不断制烟并吸烟,制烟的过程需要烟草、纸、火柴。
** 这三个进程分别掌握烟草、纸、火柴中的一种,经销商源源不断的提供原料,每次提供三种原料的两种
** 当吸烟者发现原料正是自己所缺少的,该吸烟者就会取走这两种原料,与他之前的原料混合制烟、吸烟
** 经销商发现原料被取走了,就会继续提供任意两种原料。
** 注意:
**这里不萌吧每个资源分别定义一个信号量,在编写代码
这是把原本的原子操作一分为二,会死锁
**************************************************************************************************/
semaphore Stp = 0; //烟草和纸的组合信号量
semaphore Spm = 0; //纸和火柴的组合信号量
semaphore Stm = 0; //烟草和火柴的组合信号量
semaphore buffer = 1; //缓冲区
void main(){
cobegin{
smokert(void){ //拥有烟草的吸烟进程
while(true){
P(Spm); //有纸和火柴?
fatch_paper_match();
V(buffer); //释放缓冲区
smoke();
}
}
smokerp(void){ //拥有纸的吸烟进程
while(true){
P(Stm); //有烟草和火柴?
fatch_tobacoo_match();
V(buffer); //释放缓冲区
smoke();
}
}
smokerm(void){ //拥有火柴的吸烟进程
while(true){
P(Stp); //有烟草和纸?
fatch_tobacoo_paper();
V(buffer); //释放缓冲区
smoke();
}
}
agency(void){ //经销商供货进程
int item; //用于货物识别
P(buffer);
item = put_material; //放置原料
if(item == p_m) //纸和火柴,则Spm+1
V(Spm);
else if(item == t_m) //烟草和火柴,则Stm+1
V(Stm);
else //烟草和纸,则Stp+1
V(Stp);
}
}coend
}
/**************************************************************************************************
** 吸烟者问题
** 问题描述:
** 三个吸烟者进程和一个经销商进程,每个吸烟不断制烟并吸烟,制烟的过程需要烟草、纸、火柴。
** 这三个进程分别掌握烟草、纸、火柴中的一种,经销商源源不断的提供原料,每次提供三种原料的两种
** 当吸烟者发现原料正是自己所缺少的,该吸烟者就会取走这两种原料,与他之前的原料混合制烟、吸烟
** 经销商发现原料被取走了,就会继续提供任意两种原料。
** 注意:
**这里不萌吧每个资源分别定义一个信号量,再编写代码
这是把原本的原子操作一分为二,会死锁
**************************************************************************************************/
semaphore mutex = 1; //进入库房互斥信号量
semaphore kele = M; //可乐的控制信号量,初值为M
semaphore sprit = N; //雪碧的控制信号量,初值为N
semaphore empty = C; //库房空货位信号量,初值为C
semaphore full = 0; //库房产品数信号量,初值为0
void main(){
cobegin{
keleproduce(void){ //可乐生产车间进程
while(true){
int item;
item = producekele(); //生产可乐
P(kele); //可乐是否超出吗?
P(empty); //有空位吗?
P(mutex); //互斥访问临界区(机械手空闲吗?)
putkele();
V(mutex); //释放机械手
V(full); //增加经销商提货的数量
V(sprit); //增加雪碧入库数量
}
}
spritproduce(void){ //雪碧生产车间进程
while(true){
int item;
item = producesprit(); //生产雪碧
P(sprit); //雪碧是否超出吗?
P(empty); //有空位吗?
P(mutex); //互斥访问临界区(机械手空闲吗?)
putsprit();
V(mutex); //释放机械手
V(full); //增加经销商提货的数量
V(kele); //增加可乐入库数量
}
}
consumer(void){ //经销商提货进程
while(true){
int item;
P(full) //库房有货吗?
P(mutex); //互斥访问临界区(机械手空闲吗?)
item = getkelesprit();
V(mutex); //释放机械手
V(empty);
if(item == kele)
V(kele); //增加可乐入库数量
if(item == sprit)
V(sprit); //增加雪碧入库数量
}
}
}coend
}
/**************************************************************************************************
** 打印奇、偶数问题
** 问题描述:
** 一生产者进程P,两个消费者进程C1,C2.共用一个缓冲区Pool,缓冲区Pool最多可以放N个数
** 进程P :将输入设备读入数存放于缓冲区Pool中,若满,则阻塞
** 进程C1:只将缓冲区中奇数打印,若无,则阻塞
** 进程C2:只将缓冲区中偶数打印,若无,则阻塞
**************************************************************************************************/
semaphore mutex = 1; //缓冲区互斥信号量
semaphore odd = 0; //P与C1同步(奇数)信号量
semaphore even = 0; //P与C2同步(偶数)信号量
semaphore Pool = N; //缓冲区可用数,odd+even+Pool=N
void main(){
cobegin{
P(void){ //生产进程
while(true){
int number; //临时存放数据
number = fatch();
P(Pool); //缓冲区有空闲吗?
P(mutex); //互斥访问临界区
put(number);
V(mutex);
if(number%2 == 0)
V(even); //偶数信号量+1
else
V(odd); //奇数信号量+1
}
}
C1(void){ //打印寄数进程
while(true){
P(odd); //有无奇数?
P(mutex); //互斥访问临界区
get_odd();
V(mutex);
V(Pool); //缓冲区空闲空间+1
print_odd();
}
}
C2(void){ //打印偶数进程
while(true){
P(even); //有无偶数?
P(mutex); //互斥访问临界区
get_even();
V(mutex);
V(Pool); //缓冲区空闲空间+1
print_even();
}
}
}coend
}
/**************************************************************************************************
** 理发师问题
** 问题描述:
** 理发店一间工作室(仅有1个椅子),一间接待室(最多n>=1个椅子)
** 若理发店无顾客,理发师就去睡觉
** 若新顾客看到所有的椅子都坐满人,则离开
** 接待室有空椅子且理发师正在工作,则新顾客在接待室椅子上等待
** 若理发师在睡觉,则顾客唤醒理发师
**************************************************************************************************/
semaphore mutex = 1; //缓冲区互斥信号量
semaphore customer = 0; //顾客人数
semaphore barber = 0; //理发师人数,为0表示就一个理发师
int waiting = 0; //等侯理发的人数
void main(){
cobegin{
barber(void){ //打印寄数进程
while(true){
P(customer); //有顾客吗?
p(mutex);
waiting--;
V(barber); //同步信号量,有理发师啦!
V(mutex); //这里V(barber);在前;由于竞争。就像跑步比赛一样,冠军只有一个,但是起点是一样的,要把所有的customer排在门外
cut_hair(); //理发
}
}
customer(void){ //打印寄数进程
p(mutex);
if(waiting < n){ //等待人数最多为n
waiting++;
V(customer); //新顾客人数加一
V(mutex);
P(barber); //由于barber仅有一个,所有进程在这全挂起,即坐着等候
goto_hairroom(); //去理发师房间理发
}
else
V(mutex);
}
}coend
}
/**************************************************************************************************
** 公交车问题
** 问题描述:
** 一个司机,一个门,一个售票员,请给出售票员进程、司机进程
** 司机只有等门关好了才能开车
** 只有车停好了,售票员才能开门
** 售票员可以通过观察与询问预先知道是否有乘客下车,若没有,则不用停车
**************************************************************************************************/
semaphore mutex_drive = 1; //同步信号量,由售票员发出信号,即人是否下完车或上完车了
semaphore mutex_stop = 0; //同步信号量,由售票员发出信号,是否需要停车
semaphore mutex_open_door = 0; //同步信号量,由司机发出信号,是否可以开门
semaphore mutex_close_door = 0; //同步信号量,由司机发出信号,是否可以关门
void main(){
cobegin{
drive(void){
while(true){
P(mutex_drive); //人上齐了吗?
V(mutex_close_door); //售票员,把门关上!
drive(); //开车
P(mutex_stop); //有人要下车吗?售票员,快回答我!
stop();
V(mutex_open_door); //车停好了,可以开门了
}
}
conductor(void){
while(true){
P(mutex_close_door); //好,门关了
close_door();
while(!nobody_will_leave()) just_wait();
V(mutex_stop); //有人要下车
P(mutex_open_door); //车停好了吗?
open_door();
while(!nobody_leave_finish()) just_wait(); //等待上下车结束
V(mutex_drive); //人上齐了
}
}
}coend
}
/**************************************************************************************************
** 生产者、消费者问题
** 问题描述:
** 仅有一个缓冲区,互斥访问
** 只有缓冲区有产品且无生产者访问临界区,消费者才能消费
** 只有缓冲区有空位且无消费者访问临界区,生产者才能生产
**************************************************************************************************/
semaphore mutex = 1; //缓冲区互斥信号量
semaphore full = N; //产品个数
semaphore empty = 1; //空位个数
int buffer[N];
void main(){
cobegin{
producer(void){ //生产者进程
int i = 0;
while(true){
P(empty); //有空位吗?
P(mutex);
buffer[i++] = produc_item;
i = i % N; //构成循环缓冲
V(mutex);
V(full); //快来消费,产品+1
}
}
customer(void){ //消费者进程
int i = 0;
while(true){
P(full); //有产品吗?
P(mutex);
consume_item = buffer[i--];
int i = i % N; //构成循环缓冲
V(mutex);
V(empty); //空位+1
}
}
}coend
}
/**************************************************************************************************
** 读者-写者问题(读者优先)
** 问题描述:
** 读者优先
** 读者优先意味着新到的读者“插队”,这时写者很憋屈!!直到没有读者为止才可以读
** 写写不能同时,可以多个读者读
**************************************************************************************************/
semaphore write_db = 1; //互斥信号量,互斥读操作
semaphore mutex_rc = 1; //互斥信号量,互斥访问rc
int rc = 0; //读者的数量
void main(){
cobegin{
reader(void){ //读进程
while(true){
P(mutex_rc);
if(rc++ == 0) //第一个读者来的时候,看有写者没?(相等,第一个读者哦)
P(write_db);
V(mutex_rc);
read_data();
P(mutex_rc);
if(rc-- == 0) //读者全读完了,有写者马上写,举个例子:读者数量由5,4,3···1.减到0,没读者啦,开始写!
V(write_db);
V(mutex_rc);
}
}
writer(void){ //写进程
while(true){
P(write_db); //写进程会被阻塞,由于之前有写读进程 P(write_db);
write_data();
V(write_db);
}
}
}coend
}
/**************************************************************************************************
** 读者-写者问题(写者优先)
** 问题描述:
** 写者优先
** 写者优先意味着新到的写者“插队”,这时读者很憋屈!!直到没有写者为止才可以读
** 写写不能同时,可以多个读者写
** 为了保证写者优先,在写进程通过if让读阻塞
** 当然reader()内本就会控制写者,因读的时候不能写。
**************************************************************************************************/
semaphore read_db = 1; //互斥信号量,互斥写操作,仅有一个读
semaphore write_db = 1; //互斥信号量,互斥读操作,仅有一个写
semaphore mutex_rc = 1; //互斥信号量,互斥访问rc
semaphore mutex_wc = 1; //互斥信号量,互斥访问wc
int rc = 0; //读者的数量
int wc = 0; //写者的数量
void main(){
cobegin{
reader(void){ //读进程
while(true){
P(read_db); //没有写者了,才能读(一直等,看着写者插队)
P(mutex_rc);
if(rc++ == 0) //第一个读者来的时候,看有写者没?(相等,第一个读者哦)
P(write_db);
V(mutex_rc);
V(read_db);
read_data(); //可以有多个读者,不需要互斥访问
P(mutex_rc);
if(rc-- == 0) //读者全读完了,有写者马上写,举个例子:读者数量由5,4,3···1.减到0,没读者啦,开始写!
V(write_db);
V(mutex_rc);
}
}
writer(void){ //写进程(主)
while(true){
P(mutex_wc); //这里和“读者优先”的读进程类似,写进程优先,是为了阻塞读进程
if(rc++ == 0) //第一个写者来的时候(相等,第一个写者哦),此时读阻塞
P(read_db);
V(mutex_wc);
P(write_db); //仅有一个写进程可以写
write_data();
V(write_db);
P(mutex_wc);
if(rc-- == 0) //直到所有写者都写完了(有写者就插队)举个例子:写者数量由5,4,3···1.减到0,没写者啦,开始读!
V(read_db);
V(mutex_wc);
}
}
}coend
}
/**************************************************************************************************
** 哲学家就餐问题(0号哲学家是左撇子)
** 问题描述:
** 假设0号哲学家是左撇子
**************************************************************************************************/
#define N 5
semaphore chopsticks[N]; //互斥信号量,互斥访问rc
void pickup_chopsticks(int i){ //拿起左右筷子
if(i == 0){ //处理0号哲学家的特殊
P(chopsticks[i]);
P(chopsticks[(i+1)%N]);
}else{
P(chopsticks[(i+1)%N]);
P(chopsticks[i]);
}
}
void pickdwn_chopsticks(int i){ //放下左右筷子
V(chopsticks[i]);
V(chopsticks[(i+1)%N]);
}
void main(){
while(true){
think();
pickup_chopsticks(i);
eat();
pickdwn_chopsticks(i);
}
}
/**************************************************************************************************
** 放映电影问题
** 问题描述:
** 录像厅有三种1、2、3不同影片可供观众选择放映,需满足如下条件
** 1:任一时刻只能放映一种电影,放映是自动放映的, 最后一个观众主动离开则结束当前放映
** 2:当前正在放映的观众可立即进入,观看同一种电影人数没有限制
** 3:此时观看其他的电影的人需要按到达顺序等候(如此时放映1,则2,3分别排成一队),一种
新电影放映时,等候该队列的人全部入场
** 4:用一个进程代表一个观众
** 注意:
1:由于观看人数有限制,只能满足一部分要求,而另外两队人必须等待,
2:由于看电影的人数有多人,故要分别设置三个计数器变量count1,count2,count3,初值均为0
3:为三部电影分别设置信号量S1,S2,S3,初值都为1,表示对count1,count2,count3互斥访问
**************************************************************************************************/
Semaphore S1 = 1; //对count1互斥访问
Semaphore S2 = 1; //对count2互斥访问
Semaphore S3 = 1; //对count3互斥访问
Semaphore S = 1; //只能放映一种电影
int count1 = 0; //看m1电影的数量
int count2 = 0; //看m2电影的数量
int count3 = 0; //看m3电影的数量
void main(){
cobegin{
watch_m1(void){ //看m1电影
P(S1); //对count1互斥访问
count1 = count1+1; //这种if方式是设计的一种模板吧,读者写者!!
if(count1 == 1) //谁先抢到S,就要等数量减至0,才会放弃临界区
P(S);
V(S1);
看电影1;
P(S1);
count1 = count1-1;
if(count1 == 0) //减到0,放弃临界区
P(S);
V(S1);
}
watch_m2(void){ //看m2电影
P(S2); //对count2互斥访问
count2 = count2+1;
if(count2 == 2)
P(S); //谁先抢到S,就要等数量减至0,才会放弃临界区
V(S2);
看电影2;
P(S2);
count2 = count2-1;
if(count2 == 0) //减到0,放弃临界区
P(S);
V(S2);
}
watch_m3(void){ //看m3电影
P(S3); //对count3互斥访问
count3 = count3+1;
if(count3 == 3)
P(S); //谁先抢到S,就要等数量减至0,才会放弃临界区
V(S3);
看电影3;
P(S3);
count3 = count3-1;
if(count3 == 0) //减到0,放弃临界区
P(S);
V(S3);
}
}coend
}
/**************************************************************************************************
** 小和尚和老和尚打水问题
** 问题描述:
** 某寺庙有老、小和尚若干,小和尚提水,老和尚喝水,每次喝一桶
** 1:水缸可以装10桶水,水来自水中,井窄,一次只能放一个桶
** 2:水桶有三个。每次入杠仅只一桶水,取水,注水不可同时进行
** 4:取水,注水进程
** 注意:
1:由于观看人数有限制,只能满足一部分要求,而另外两队人必须等待,
2:由于看电影的人数有多人,故要分别设置三个计数器变量count1,count2,count3,初值均为0
3:为三部电影分别设置信号量S1,S2,S3,初值都为1,表示对count1,count2,count3互斥访问
**************************************************************************************************/
//同步信号量
Semaphore empty = 10; //缸可以装10通水
Semaphore full = 0; //与empty是一对,设计方法!
//互斥信号量
Semaphore mutex_well = 1; //对count3互斥访问
Semaphore mutex_vat = 1; //只能放映一种电影
Semaphore pail = 3; //水桶数量3个
void main(){
cobegin{
xiao_Monk(void){ //小和尚打水
P(empty); //需要打水吗?
P(pail); //有桶吗?
P(mutex_well); //互斥访问井
从井取一桶水;
V(mutex_well);
P(mutex_vat); //互斥访问缸
将水倒入缸中
V(mutex_vat);
V(full);
V(pail); //放下桶
}
lao_Monk(void){ //看m2电影
P(full); //有水吗?
P(pail); //有桶吗?
P(mutex_vat); //互斥访问缸
从缸里取水;
V(mutex_vat);
P(empty);
喝水;
V(pail);
}
}coend
}
/**************************************************************************************************
** 信封问题
** 问题描述:
** A,B两人进行辩论,
** 1:每个人都从自己的信封里取出对方的问题,并回答其中问题,之后提出一个新问题放入对方的邮箱里
** 2:A信箱最多放M封信,B信箱最多放N封信
** 3:初始A信箱有x(0=3),每个位置可以放一个车架或车轮,有三个工人
** 1:加工一个车架,车架放入箱中
** 2:加工一个车轮,车轮放入箱中
** 3:取两个车轮和一个车架,组装成一辆自行车
** 注意:
1:最多可以放的车轮数:N-1
2:最多可以放的车架数:N-2
**************************************************************************************************/
Semaphore wheel = 0; //车轮数
Semaphore frame = 0; //车架数
Semaphore empty = N; //空位数
Semaphore wheel_M = N-1; //最多可以放的车轮数,极限要有一个车架
Semaphore frame_M = N-2; //最多可以放的车架数,极限要有两个车轮
void main(){
cobegin{
worker1(void){ //工人1
while(TRUE){
加工一个车架;
P(frame_M); //检查车架是否达最大
P(empty);
车架放入箱中;
V(frame); //车架数加1
}
}
worker2(void){ //工人2
while(TRUE){
加工一个车轮;
P(wheel_M); //检查车架是否达最大
P(empty);
车轮放入箱中;
V(wheel); //车轮数加1
}
}
worker3(void){ //工人3
while(TRUE){
P(frame); //取一个车架
取一个车架;
V(empty);
V(frame_M); //可用车架数架1
P(wheel); //取两个车轮
P(wheel);
取两个车轮;
V(wheel_M);
V(wheel_M);
V(empty);
V(empty);
}
}
}coend
}
/**************************************************************************************************
** 独木桥问题
** 问题描述:
** 独木桥只能单向行驶,一个方向车还没有过完时,另外方向不能过
** 1:不防假设南北方向通行
**************************************************************************************************/
Semaphore mutexSN = 1; //保护countSN
Semaphore mutexNS = 1; //保护countNS
Semaphore bridge = 1; //互斥访问桥
int countSN = 0; //计数变量(由南到北的车辆数)
int countSN = 0; //计数变量(由北到南的车辆数)
void main(){
cobegin{
SToN(void){ //由南到北
P(mutexSN); //检查车架是否达最大
if(countSN == 0)
P(bridge); //谁先来,谁先过
countSN++;
P(mutexSN);
过桥;
P(mutexSN);
countSN--;
if(countSN == 0) //该方向没有车辆了
V(bridge);
P(mutexSN);
}
NTos(void){ //由北到南
P(mutexNS);
if(countNS == 0)
P(bridge);
countNS++;
P(mutexNS);
过桥;
P(mutexNS);
countNS--;
if(countNS == 0) //该方向没有车辆了
V(bridge);
P(mutexNS);
}
}coend
}
链接:https://pan.baidu.com/s/1VpOOH3OP7AiDMedgeZFPQg 密码:eq4y