生产者消费者问题
生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
解法
1)关系分析:生产者和消费者对缓冲区互斥访问是互斥关系,同时生产者和消费者又是一个相互协作的关系,只有生产者生产之后,消费者才能消费,他们也是同步关系。
2)整理思路:只有生产者和消费者两个进程,正好是这两个进程存在着同步和互斥关系,需要解决的问题就是PV操作的位置。
3)信号量设置:信号量mutex作为互斥信号量,用于控制互斥访问缓冲池,初值为1;信号量full用于记录当前缓冲池中“满”缓冲区数,初值为0;信号量empty用于记录缓冲池中“空”缓冲区数量,初值为n。
伪代码
semaphore full=0;
semaphore empty=N;
semaphore mutex = 1;
void P(semaphore);
void V(semaphore);
void producer(){
while(1){
//...producer data
P(empty);
P(mutex);
//...add the data to buffer
V(mutex);
V(full);
//....other
}
}
void consume(){
while (1)
{
//...other
P(full);
P(mutex);
//...remove from buffer data
V(mutex);
V(empty);
//...consumer the data
}
}
哲学家进餐问题
五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们边吃边想。一个哲学家饥饿时取他左右最靠近的筷子,只有拿到两只筷子才能进餐,吃完继续想。
问题分析:
1)关系分析:5名哲学家与左右邻居对其中间筷子的访问是互斥关系。
2)整理思路:五个进程,问题的关键在于让一个哲学家拿到左右两个筷子而不造成死锁或饥饿现象。解决方法有两个,一个是让他们同时拿两个筷子;一个是对每个哲学家的动作制定规则。
3)信号量设置:定义互斥信号量数组chopstick[5]={1,1,1,1,1},用于对5个筷子的互斥访问。
对哲学家按顺序从0到4编号,i号哲学家左边的筷子编号为i,右边的为(i+1)%5。
4)当一个哲学家左右两边的筷子都可用时,才允许他抓起筷子。
伪代码
#define N 5
semaphore mutex = 1;
semaphore chopstick[N];
void init(){
for(int i=0;i<N;++i)chopstick[i]=1;
}
void P(semaphore);
void V(semaphore);
void philosopher(int i){
while(1){
P(mutex);
P(chopstick[i]);
P(chopstick[(i+1)%N]);
V(mutex);
//...eating
V(chopstick[i]);
V(chopstick[(i+1)%5]);
//....thinking
}
}
当五个哲学家同时去取他左边的筷子,每人拿到一只筷子且不释放,即五个哲学家只得无限等待下去,引起死锁。
利用and信号量解决
#define N 5
semaphore mutex = 1;
semaphore chopstick[N];
void init(){
for(int i=0;i<N;++i)chopstick[i]=1;
}
void Swait(semaphore,semaphore);
void Ssinged(semaphore,semaphore);
void philosopher(int i){
while(1){
Swait(chopstick[i],chopstick[(i+1)%5]);
//...eating
Ssinged(chopstick[i],chopstick[(i+1)%5]);
//....thinking
}
}
读者-写者问题
读者写者问题----读者优先(python测试)
读者写者问题----写者优先(python测试)
读者写者问题----公平策略(python测试)
打瞌睡的理发师问题
理发店理有一位理发师、一把理发椅和n把供等候理发的顾客坐的椅子,要求:
- 如果没有顾客,理发师便在理发椅上睡觉
- 一个顾客到来时,它必须叫醒理发师
- 如果理发师正在理发时又有顾客来到,则如果有空椅子可坐,就坐下来等待,否则就离开
伪代码
#define chairs 5
// 等候椅子数
semaphore consumers= 0; //顾客数
semaphore barners = 0; // 剩余理发师数
semaphore mutex = 1; // 互斥操作
int waiting; // 等待的顾客数
void P(semaphore);
void V(semaphore);
void barber(){
while(true){
P(consumers);
P(mutex);
waiting--;
V(barners);
V(mutex);
// 准备理发
}
}
void consumer(){
P(mutex);
if(waiting<chairs){
waiting++;
V(consumers);
V(mutex);
P(barners); // wait to haircut....
// prepare to haircut
}else V(mutex); // consumer exit
}