生产者-消费者问题

生产者-消费者问题

十二月 02, 2019

进程调度笔记(1)


首先我们要知道什么是信号量
信号量(Semaphore),是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用.
在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量.
其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量.

其次我们要知道什么是生产者-消费者问题

现在,我们有一个固定大小的缓冲区,有两个线程,一个是从这个缓冲区中读取数据(消费者),一个是从这个缓冲区中写入数据(生产者)
于是便产生了问题:生产者不能一直写数据,因为缓冲区的大小是有限的;同理,消费者也不能一直读数据,因为缓冲区会空

于是引入两个操作P V
这两个操作是原子操作(意思就是运行时不会被中断)

P操作:

1
2
3
4
5
P(S)
{
while(S <= 0);
S--;
}

V操作:

1
2
3
4
V(S)
{
S++;
}

知道了这些,让我们回到问题

于是我们有了如下代码:

1
2
3
4
semaphore mutex = 1; //互斥
semaphore empty = n;
semaphore full = 0;
// 定义全局变量
1
2
3
4
5
6
7
8
9
Produce()
{
while(true)
{
P(empty);
product(); //生产1
V(full);
}
}
1
2
3
4
5
6
7
8
9
Consume()
{
while(true)
{
P(full);
consume(); //消费1
V(empty);
}
}

其实到这里,程序就写完了,但是有一个问题,假如我生产时,CPU突然跑过去给消费者了,然后再回来时,就有两个生产者进程了.为了解决这个问题,我们引入了互斥信号量mutex

于是更改代码

1
2
3
4
5
6
7
8
9
10
11
Produce()
{
while(true)
{
P(mutex);
P(empty);
product(); //生产1
V(full);
V(mutex);
}
}
1
2
3
4
5
6
7
8
9
10
11
Consume()
{
while(true)
{
P(full);
P(mutex);
consume(); //消费1
V(empty);
V(mutex);
}
}

此时问题已经解决完了.但是,P(empty)和P(mutex)可以交换位置吗?
答案显然是不行

因为,当你的empty为0的时候(极端情况),你生产者拿到了mutex的信号量,但是没拿到empty的信号量,于是进程阻塞.


以上就是我对生产者-消费者模型的总结,有什么理解错误的地方还希望大家指出啊!
QQ:527430509