如何使用POSIX信号量实现屏障?

3
如何使用POSIX信号量实现屏障?
void my_barrier_init(int a){

    int i;  
    bar.number = a;
    bar.counter = 0;

    bar.arr = (sem_t*) malloc(sizeof(sem_t)*bar.number);
    bar.cont = (sem_t*) malloc(sizeof(sem_t)*bar.number);
    for(i = 0; i < bar.number; i++){    
    sem_init(&bar.arr[i], 0, 0);
    sem_init(&bar.cont[i], 0, 0);   }
}

void my_barrier_wait(){
    int i;    
    bar.counter++;

    if(bar.number == bar.counter){      
    for(i = 0; i < bar.number-1; i++){  sem_wait(&bar.arr[i]);    }
    for(i = 0; i < bar.number-1; i++){   sem_post(&bar.cont[i]);     }
    bar.counter = 0;
    }else{
        sem_post(&bar.arr[pthread_self()-2]);
        sem_wait(&bar.cont[pthread_self()-2]);
  }
}

当函数my_barrier_wait被调用时,首先(N-1)次它会对数组'arr'中的信号量进行设置(+1),并进入休眠状态(调用sem_wait)。第N次会将'arr'数组中的信号量减少,并且应该(按照我的期望)唤醒[0..bar.number-1]线程,在'cont'数组中为信号量发布+1。 但是它的工作方式不像屏障。

pthread_self()的手册中可以看出:"线程标识符应被视为不透明。" - Celada
当我测试它时,信号量正常工作,getvalue返回了预期的数字。无论如何,谢谢,我可能会修复它。但是这有助于让它像屏障一样工作吗? - diana-pure
1
不,它没有。但是你并没有真正说明出了什么问题(只是说“它不像屏障一样工作”),所以很难猜测问题在哪里。也许需要使用互斥锁来保护bar.counter免受并发更新的影响? - Celada
坦白说,这段代码只是我的尝试(它已经编译了,但N个线程只在第一次等待彼此一次,然后它们逐个地在屏障上唤醒,而不是全部一起)。我正在寻求一个可行的算法。 - diana-pure
1
乍一看,这段代码看起来还好,除了bar.counter没有受到保护,可能会被多个线程同时修改。我可能会忽略一些细节(并行算法很难理解),但你应该从bar.counter开始着手。然后,我猜你可以添加调试输出,显示每个线程在等待之前/之后的状态,也许输出会展示一种你没想到的状态,这就是一个线索。 - Celada
显示剩余2条评论
1个回答

1
你需要查看this(PDF),阅读Allen Downey编写的《信号量小书》第3.6.7节。虽然是用Python编写的,但其主要思路应该很清晰。

1
链接现在是404。 - Michał Górny
@MichałGórny,我现在拼命地试图回忆起它说了什么!试试这个 :-) https://greenteapress.com/semaphores/LittleBookOfSemaphores.pdf - bazza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接