操作系统经典进程同步问题之生产者-消费者问题
- 先通俗的理解一下什么是同步:进程同步其实好比就是一件事情必须先做什么再做什么,否则不能继续下去,就比如有3个进程A,B,CA是输出进程,B是处理进程,C是输出进程,假如A进程没有输入数据,那么B进程就无法进行处理,只有A输出了,B才能继续,这就是进程同步
一、生产者-消费者问题
1.问题描述:生产者-消费者模型描述的是有一群生产者进程在生产产品,并将这些产品提供给消费者进程并发进行,具备并发程序的典型特征。PCM为使生产者进程和消费者进程并发进行,在它们之间设置一个具有多个缓冲区的缓冲池生产者进程可以将其所生产的产品放入一个缓冲区中,消费者进程可以从一个缓冲区中取得产品去消费。尽管所有的生产者进程和消费者进程都是以异步方式运行的,但他们之间必须保持同步,既不允许消费者进程从空的缓冲区中拿产品,也不允许生产者进程向满缓冲区中放产品。
2.问题分析:我们可以利用一个数组来表示上述的具有n各缓冲单元的缓冲区。用输入指针in作写指针,每当生产者进程生产并投放一个产品时,in加1;同理,out指针作为读指针,每当消费者拿走一个产品时out便加1。由于缓冲区是循环队列,则加1写成,in=(in+1)mod n,out同理。当(in+1)mod n=out时,缓冲区满,当in=out时,缓冲区为空。此外还引入了count,当生产者生产并放入时加1,消费者拿走时则减1.
3.程序描述:
共享变量
int n, buffer[n];
int in, out; //in,out[0,n-1]
int count; //count[0,n]
伪代码:
void producer() {
producer an item in nextp;
while (count == n) {
buffer[in] = nextp;
in = (in + 1)mod n;
count++;
}
void consumer() {
while (count==0) {
nextc = buffer[out];
out = (out + 1)mod n;
count--;
consumer the item in nextc;
}
利用记录型信号量解决
int mutex = 0, empty = n, full = 0;
int buffer[n];
int in = 0, out = 0;
void producer() {
producer an item, nextp;//nextp为生产的产品
wait(empty);
wait(mutex);
buffer[in] = nextp;
in = (in + 1)mod n;
signal(mutex);
signal(full);
}
void consumer() {
wait(full);
wait(mutex);
nextc = buffer[out];
out = (out + 1)mod n;
signal(mutex);
signal(empty);
consumer nextc;
}
记录型信号量中wait(),和signal()操作如下:
void wait(s) { //s为信号量
s--;
if (s < 0) {
block(s,L)//阻塞
}
}
void signal(s) {
s++;
if (s <=0) {
wakeup(s, L);//唤醒
}
每个程序中用于实现互斥的wait(mutex)和signal(mutex)必须成对出现,注意wait(empty)在生产者进程中,每个程序中多个wait操作不可颠倒,否则容易发生死锁的现象。