3.1
临界区问题
异步并发进程或线程之间或者是彼此独立不相关的,或者彼此之间有相互影响。这些影响可以
是数据的共享、信息的传递、控制流之间的相互影响,等等。当并发进程之间相互存在关系时,它们
的并发运行就需要处理一些特别的情况,这就是本章的主题。
我们先探讨最常见的若干协作进程或线程,这些进程或线程均异步执行且共享数据。最典型的
具有代表性的问题有“生产者一消费者问题”。我们前面已特地采用了有限缓冲方案来处理进程共
享内存的问题。
现在回到有限缓冲问题的共享内存解决方案。正如先前所指出的,该解决方案允许同时在缓冲
区内最多只有
BUFFER_SIZE-1
项。假如要修政这一算法以弥补这个缺陷。一种可能方案是增加一个
整数变量
counter
,并初始化为
0
。每当向缓冲区增加一项时,
counter
就递增;每当从缓冲区移走一
项时,
counter
就递减。
按照这个思路,生产者进程代码可修改如下:
while (true) {
/* produce an item in nextProduced */
while (counter == BUFFER—SIZE)
;
/* do nothing */
buffer[in] = nextProduced;
in =(in+l) % BUFFER_SIZE;
counter++;
}
类似地,消费者进程代码可修改如下:
while (true) {
while (counter == 0)
; /* do nothing */
nextConsumed = buffer[out]:
out = (out + 1) % BUFFER_SIZE;
counter--;
/* consume the item in nextConsumed */
}
虽然生产者和消费者程序各自都是正确的,但是当并发执行时它们可能不能正确运行!
为了便于说明,假设变量
counter
的值现在为
5
,且生产者进程和消费者进程正在并发执行
语句“
counter++”
和“
counter--”
。显然,唯一正确的结果应是
counter == 5
。但是,根据
这两条语句的具体执行顺序,变量
counter
的值却可能是
4
、
5
或
6
!为什么呢?因为,语句
“
counter++”
在一台典型的机器上很可能是按如下方式以机器语言实现:
register1 = counter
register1 = register1+l
counter = register1
其中,
register1
为
CPU
局部寄存器。类似地,语句“
counter--”
可按如下方式来实现:
register2 = counter
register2 = register2-1
评论0