信号量呈菱形

Semaphores as a diamond

本文关键字:信号量      更新时间:2023-10-16

我的作业是在一个菱形模式的信号量数组上执行等待和信号。

模式如下:

    08
  06  07  
03  04  05
  01  02
    00
Thread #08 cannot join the diamond until threads #06 and #07 are both in position.
Thread #07 cannot join until threads #04 and #05 are both in position.
Thread #06 cannot join until threads #03 and #04 are both in position. and so on...
到目前为止,我的想法导致了以下丑陋的算法:
   if (me==0) {
       wait_sem (tCount[1]) ;
       wait_sem (tCount[2]) ;
       signal_sem (tCount[0]) ;
   }
   if (me==1) {
       wait_sem (tCount[3]) ;
       wait_sem (tCount[4]) ;
   }
   if (me==2) {
       wait_sem (tCount[4]) ;
       wait_sem (tCount[5]) ;
   }
   if (me==3) {
       wait_sem (tCount[6]) ;
   }
   if (me==4) {
       wait_sem (tCount[6]) ;
       wait_sem (tCount[7]) ;
   }
   if (me==5) {
       wait_sem (tCount[7]) ;
   }
   if (me==6) {
       wait_sem (tCount[8]) ;
   }
   if (me==7) {
       wait_sem (tCount[8]) ;
   }

有没有更干净的方法来做这件事?我听说过switch,但我以前从未使用过它,所以如果有人建议它,请给我一个解释或例子。

让我们采用一种非常简单的方法,将信号量保存在全局数组中(或者仅供线程访问)。你可以像这样设置一个依赖列表:

std::vector<std::vector<int>> thread_depends = {
    { },      // 0
    { 0 },    // 1
    { 0 },    // 2
    { 1 },    // 3
    { 1, 2 }, // 4
    { 2 },    // 5
    { 3, 4 }, // 6
    { 4, 5 }, // 7
    { 6, 7 }, // 8
};

现在,每个线程只需要等待thread_depends[me]中的所有内容:

const auto & dep = thread_depends[me];
std::for_each( dep.begin(), dep.end(), [&tCount](int who){ wait_sem( tCount[who] ); } );
signal_sem( tCount[me] );

这种方法的好处是,您不需要重复每种情况下要做什么的逻辑。相反,您只是表示依赖项,并且只有一段代码可以完成实际的工作。这意味着更少的机会犯复制粘贴错误。

这个解决方案只是为了展示如何使用case来完成,对于这个问题还有更好的实现!

Switch比if's/else更好,因为它像跳转一样工作,当if's需要测试所有条件直到满足(if0, if1, if2…)时,Switch将直接切换到正确的情况。

switch(me)
{
    case 0:
        wait_sem(tCount[1]);
        wait_sem(tCount[2]);
        signal_sem(tCount[me]);
        break;
    case 1:
        wait_sem(tCount[3]) ;
        wait_sem(tCount[4]) ;
        signal_sem(tCount[me]);
        break;
    case 2:
        wait_sem(tCount[4]);
        wait_sem(tCount[5]);
        signal_sem(tCount[me]);
        break;
    case 3:
        wait_sem(tCount[6]);
        signal_sem(tCount[me]);
        break;
    case 4:
       wait_sem(tCount[6]);
       wait_sem(tCount[7]);
       signal_sem(tCount[me]);
       break;
    case 5:
       wait_sem(tCount[7]);
       signal_sem(tCount[me]);
       break;
    case 6:
       wait_sem(tCount[8]);
       signal_sem(tCount[me]);
       break;
    case 7:
       wait_sem(tCount[8]);
       signal_sem(tCount[me]);
       break;
    case 8:
       signal_sem(tCount[me]);
       break;
}