屏障是一种同步构造,其中一组进程全局同步,即集合中的每个进程到达屏障并等待所有其他进程到达,然后所有进程都离开屏障。假设集合中的进程数为3,S为具有常用P和V函数的二进制信号量。考虑以下C实现的屏障,左侧显示行号。
void barrier (void) {
1: P(S);
2: process_arrived++;
3: V(S);
4: while (process_arrived !=3);
5: P(S);
6: process_left++;
7: if (process_left==3)
{
8: process_arrived = 0;
9: process_left = 0;
10: }
11: V(S);
}
变量process_arrived和process_left在所有进程之间共享,并初始化为零。在并发程序中,当需要全局同步时,所有这三个进程都会调用屏障函数。
上述实施是否有效?我认为如果立即连续使用两个屏障调用可能会导致死锁,因为进入屏障的第一个进程不会等到process_arrived变为零之后再继续执行P(S)。
答案 0 :(得分:1)
提到有3个过程。让它成为P1,P2& P3。每个进程都到达屏障,即完成代码的第一部分。因此,process_arrived = 3.现在假设P1继续执行并离开屏障并使process_left = 1。现在假设P1再次立即调用屏障功能。在此阶段,process_arrived = 4。 P1现在等待。很快P2离开了障碍,这使得process_left = 2。现在P3离开了使process_left = 3的屏障。 "如果" condition为true,现在为process_arrived,process_left重置为0。 我们知道P1正在等待。在此阶段假设P2调用屏障函数,因此process_arrived = 1并等待。 P3调用屏障函数,因此process_arrived = 2。所有进程都已达到障碍,但由于process_arrived = 2,所有进程都在等待。因此陷入僵局。
答案 1 :(得分:0)
嗯......限制为三个线程,只有二进制信号量,我很想尝试使用三个信号量,A,B,C。控制访问process_arrived计数,B和C是第一个和第二个等待的线程。 A初始化为1,B& C到0.线程1获得A,因此防止2& 3进入。在process_arrived上启用导致线程1执行process_arrived,释放A并等待B.线程2获得A,并且交换机使其进入process_arrived,切换并释放A并等待C.线程3获得A并且交换机导致它发信号B,信号C,设置process_arrived为0,信号A并继续。
线程1和2不能通过B和C,直到3发出信号。当B / C通过3发出信号时,1/2可以运行但不能循环回到屏障直到3次释放A,此时屏障处于正确的状态再次充当屏障 - A计数1,B和C为零,process_arrived为零。