使用二进制信号量实现屏障(一种同步结构)

Posted

技术标签:

【中文标题】使用二进制信号量实现屏障(一种同步结构)【英文标题】:Implementation of a Barrier(a synchronization construct) using binary semaphore 【发布时间】:2011-12-22 01:59:01 【问题描述】:

Barrier 是一种同步结构,其中一组进程全局同步,即集合中的每个进程到达屏障并等待所有其他进程到达,然后所有进程离开屏障。令集合中的进程数为 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)。

【问题讨论】:

好吧。如果我们假设在调用 barrier() 之前信号量已经初始化为 1,那么所有 3 个线程都应该在 4 处进入讨厌的自旋状态,除非处理器数量小于 3 并且第一个到达的线程的优先级更高比后一个/s,在这种情况下系统将活锁。如果 3 确实设法在循环中出现,则将在 5 处获得锁并通过,将 process_left 设置为 1,但将 process_arrived 设置为 3。然后它可以释放信号量,做一些事情,循环。再次调用 barrier() 并将 process_arrived 设置为 4.... 在所有线程都进入屏障之前,不允许线程离开屏障,然后所有线程必须离开屏障,然后任何线程才能再次进入。 然后是全局问题.. 谢谢马丁。进入前检查process_arrived的值,离开前检查process_left的值是否有助于解决这个问题? 这可能会迟到,但我有一个问题,如果 2 个进程同时出现,可能不会出现死锁,但随后第三个进程出现并无限期等待 4,因为直到现在 process_arrived = 2。我说的对吗? 【参考方案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 的障碍。 “如果”条件为真,现在 process_arrived 和 process_left 重置为 0。 我们知道 P1 正在等待。在这个阶段假设 P2 调用屏障函数,因此 process_arrived=1 并等待。 P3 调用屏障函数,因此 process_arrived=2。所有进程都已到达障碍,但由于 process_arrived=2,所有进程继续等待。因此陷入僵局。

【讨论】:

我实际上不确定死锁是如何发生的。请评论一下,如果我猜对了吗?【参考方案2】:

嗯...仅限于三个线程并且只能使用二进制信号量,我很想尝试使用三个信号量 A、B、C。A 控制对 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为零。

【讨论】:

以上是关于使用二进制信号量实现屏障(一种同步结构)的主要内容,如果未能解决你的问题,请参考以下文章

使用互斥量和信号量的屏障实现

使用信号量实现 N 个进程屏障

修改为“使用信号量实现 N 进程屏障”

Java并发和高并发学习总结- J.U.C之工具类

《Linux内核设计与实现》读书笔记- 内核同步方法

《Linux内核设计与实现》读书笔记- 内核同步方法