信号量作为钻石

时间:2016-11-15 04:03:53

标签: c++ algorithm semaphore

我的作业是以钻石图案对一系列信号量进行等待和发出信号。

以下是模式:

    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但我以前从未使用它,所以如果有人建议,请给我一个解释和示例。非常感谢所有的投入。

2 个答案:

答案 0 :(得分:3)

让我们采用一种非常简单的方法,将信号量保存在全局数组中(或者只是可以访问线程)。您可以设置依赖项列表,如下所示:

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] );

这种方法的好处是你不会复制每个案例的操作逻辑。相反,您只是代表依赖项,而您只有一段代码可以完成实际工作。这意味着制作复制粘贴错误的可能性更小。

答案 1 :(得分:1)

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

切换比if / else更好,因为它可以作为跳转,如果需要测试所有条件直到满足(if0,if1,if2 ......),交换机将直接到正确的案例。

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;
}