3.5
经典同步问题
在本节,将介绍几种不同的同步问题,以作为大量并发控制问题的典型例子。这些问题也一直
被用来测试各种同步方案。在这里,我们将采用信号量作为同步问题的解决方案。
3.5.1
有限缓冲区问题(
bounded-buffer problem
,生产者消费者问题)
有限缓冲区问题先前已讨论过,它通常用来说明同步原语的能力。这里,介绍一种该方案的通用
解决结构,而不是只局限于某个特定实现。
假定缓冲池有
n
个缓冲项,每个缓冲项能存放一个数据项。二进制信号量
mutex
提供了对缓冲池
访问的互斥要求,并初始化为
l
。计数信号量
empty
和
full
分别用来表示空缓冲项和满缓冲项的个数。
信号量
empty
初始化为
n
;而信号量
full
初始化为
0
。
生产者进程的代码如图
3.14
所示;消费者进程的代码如图
3.15
所示。注意生产者和消费者之间
的对称性。可以这样来理解代码:生产者为消费者生产满缓冲项,而消费者为生产者生产空缓冲项。
do {
// produce an item in nextp
wait(empty);
wait(mutex);
// add nextp to buffer
signal(mutex);
signal(full);
} while (TRUE);
图
3.14
生产者进程结构
do {
wait(full);
wait(mutex);
// remove an item from buffer to nextc
signal(mutex);
signal(empty);
// consume the item in nextc
} while (TRUE);
图
3.15
消费者进程结构
3.5.2
读者一写者问题(
Readers-writers problem
)
一个数据库正被多个并发进程所共享。其中,有的进程可能只需要读数据库,而其他进程可能需
要更新(即读和写)数据库。为了区分这两种类型的进程,将前者称为读者,而将后者称为写者。显
然,如果两个读者同时访问共享数据,那么不会产生什么不利的结果。然而,如果一个写者和其他
进程(既不是读者也不是写者)同时访问共享对象,很可能引起混乱。
为了确保不会产生这样的混乱,要求写者对共享数据库有排他的访问。这一同步问题称为读者
一写者问题。自从它被提出后,就一直用来测试几乎所有新的同步原语。
读者一写者问题有多个变种,都与优先级有关。最为简单的,通常也被称为第—类读者一写者
问题,要求除非已有一个写者已获得允许以使用共享数据库,否则没有读者需要保持等待。换句话
说,没有读者会因为有一个写者在等待而会等待其他读者的完成。第二类读者一写者问题则要求,