生产者/消费者问题是一个多进程进行同步的问题,需要使用信号量(semaphore)进行相关资源的控制,实现并发。一些关于并发的基础概念如下:
原子操作 一组不可分割的函数或操作。这类函数或操作的执行是不可以被中断的。
临界区 进程中一段需要访问共享资源的代码,共享资源一次只能允许一个进程访问,系统要保证进入临界区的进程不超过一个。 正常执行可以并行,临界区代码执行只能串行。
解决并发问题的核心:控制对共享资源的访问
信号量(semaphore)
用于在进程间发送信号的整形变量,该变量定义3个原子操作:
1.初始化:信号量的初始值为非负整数
2.semSignal(V):将信号量加1,如果之后信号量的值大于等于零,进程唤醒该信号量上等待的一个进程,并继续自己的执行。
3.semWait(P):将信号量减1,如果之后信号量的值为负数,调用semWait的函数将阻塞,否则进程继续执行。
互斥锁和01信号量的区别:互斥锁执行上锁和开锁的进程必须为同一进程,01信号灯可以是不同进程。
生产者/消费者问题
有一个或多个生产者,不停生产数据,将所生产的数据放到一个缓冲区中。同时有一个消费者将数据从缓冲区中取出。用信号量解决该问方法伪代码如下:
semaphore full = 0;
semaphore empty = BUFFER_SIZE;
semaphore mutex = 1;
Producer() Consumer()
{ {
produce(); P(full);
P(empty); P(mutex);
P(mutex); take();
put(); V(mutex);
V(mutex); V(empty);
V(full); consume();
} }
生产者:生产物品 -> 请求访问缓冲区空闲的资源 (没有资源阻塞,有资源继续执行) -> 给缓冲区上锁 -> 向缓冲区添加物品 -> 给缓冲区解锁 -> 释放可用面包资源
消费者:请求访问可用物品资源(没有资源阻塞,有资源继续执行)-> 给缓冲区上锁 -> 从缓冲区拿走物品 -> 给缓冲区解锁 -> 释放可用缓冲区资源 -> 消费物品
对信号量的理解 信号量的PV操作实际上是某个进程使用和释放某资源,如果进程想要使用资源,当前资源为0那么进程就会阻塞等待资源。