银弹
关系分析
找出有几个进程并分析他们之间的关系(互斥、同步、前驱)
整理思路
根据进程操作流程找出PV操作的大致顺序
设置信号量
设置需要的信号量,设置初值,完善整理
生产者-消费者问题
关系分析
显然这里有两个进程,生产者与消费者,它们之间显然是同步关系,对缓冲池的使用则是互斥的
整理思路 & 设置信号量
生产者放入数据前应检查缓冲池是否满,此为信号量1,放入后还应更新信号量2
消费者取出数据前应检查缓冲池是否空,此为信号量2
- 信号量mutex用来实现互斥访问缓冲池
伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| semaphore mutex = 1 semaphore empty = n semaphore full = 0
process producer() { while(true) { create product; P(empty); P(mutex); load product into buffer; V(mutex); V(full); } }
process consumer() { while(true) { P(full); P(mutex); get product from buffer; V(mutex); V(empty); } }
|
变种生产者-消费者问题
关系分析
显然有四个进程,儿子、爸爸、女儿、妈妈,爸爸和妈妈对于盘子的操作是互斥的,儿子与爸爸、女儿与妈妈分别是同步的
整理思路 & 设置信号量
- 首先对盘子的访问是互斥的,即为信号量
plate
- 爸爸与儿子间需要一个信号量
orange
实现同步
- 同理妈妈与女儿间需要一个信号量
apple
实现同步
- 儿子女儿之间不需要互斥
伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| semaphore plate = 1; semaphore orange = 0; semaphore apple = 0;
process dad() { while(true) { prepare orange; P(plate); put orange on plate; V(orange); } }
process mom() { while(true) { prepare apple; P(plate); put apple on plate; V(apple); } }
process son() { while(true) { P(orange); take orange from plate; V(plate); } }
process daughter() { while(true) { P(apple); take apple from plate; V(plate); } }
|
读者写者问题
关系分析
读者之间不需要同步,写者与写者之间,写者与读者之间是互斥的
整理思路 & 设置信号量
读写文件显然是互斥的,用互斥锁rw
来实现
多个读者可以同时访问文件,而只要有读者在写者就不能访问文件,说明写者与读者之间存在一个计数器count
来实现控制rw
实现互斥
不同读者之间访问计数器应是互斥的,用信号量mutex
实现
伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| semaphore mutex = 1; semaphore rw = 1; semaphore count = 0; semaphore w = 1;
process writer() { P(w); P(rw); write file; V(rw); V(w); }
process reader() { P(w); P(mutex); if (count == 0) { P(rw); } count++; V(mutex); V(w); read file; P(mutex); count--; if (count == 0) { V(rw); } V(mutex); }
|
哲学家就餐问题
关系分析
显然相互之间对叉子的访问是互斥的
整理思路 & 设置信号量
- 每个叉子用一个信号量实现互斥访问,即有信号量数组
forkes[5]
- 当两边的叉子都可用时才允许拿起叉子,用互斥锁
mutex
实现
伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| semaphore forkes[5]; semaphore mutex = 1;
process Pi() { while (true) { P(mutex); P(forkes[i]); P(forkes[(i + 1) % 5]); V(mutex); eat; V(forkes[i]); V(forkes[(i + 1) % 5]); think; } }
|
吸烟者问题
关系分析
四个进程,三个抽烟者,一个供应者,供应者供货与吸烟者卷烟的应同步,供应者供货与吸烟者吸烟应互斥
整理思路 & 设置信号量
- 三个吸烟者卷烟需要三个信号量
offer1-3
来与供应者同步
- 抽烟需要一个信号量与供应者实现互斥
伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| semaphore s1 = 0, s2 = 0, s3 = 0, mutex = 1;
process producer() { P(mutex); V(oneOf(s1, s2, s3)); V(mutex); }
process smoker1() { P(s1); make(); P(mutex); smoke(); V(mutex); } process smoker2() { P(s2); make(); P(mutex); smoke(); V(mutex); } process smoker3() { P(s3); make(); P(mutex); smoke(); V(mutex); }
|
EOF