6

如果我有一个初始化的 pthread_barrier_t,什么时候可以安全地销毁它?下面的例子安全吗?

pthread_barrier_t barrier;
...
int rc = pthread_barrier_wait(b);
if (rc != PTHREAD_BARRIER_SERIAL_THREAD && rc != 0){
  perror("pthread_barrier_wait");
  exit(1);
}

if (id == 0){
  if(pthread_barrier_destroy(&(threads[t_root].info.tmp_barrier))){
    perror("pthread_barrier_destroy");
    exit(1);
  }
}
4

2 回答 2

5

返回后pthread_barrier_wait(),所有线程都将遇到障碍并继续进行。由于只给了一个线程PTHREAD_BARRIER_SERIAL_THREAD返回值,因此可以安全地使用它来有条件地包装销毁代码,如下所示:

int rc = pthread_barrier_wait(&b)
if ( rc == PTHREAD_BARRIER_SERIAL_THREAD )
{
    pthread_barrier_destroy(&b);
}

另外,请注意,如果屏障正在使用(即另一个线程已调用) ,pthread_barrier_destroy()它将返回结果。EBUSYpthread_barrier_wait()

于 2009-05-17T13:59:51.543 回答
3

接受的答案不正确。PTHREAD_BARRIER_SERIAL_THREAD 的返回值并不意味着破坏屏障是安全的。

在破坏屏障之前,您需要额外的同步。

问题是在其他线程正在离开屏障的过程中可能会发生销毁调用。由于 futex 系统调用可能有“错误唤醒”,这些线程需要检查屏障的状态。如果屏障使用的内存从它们下面释放出来,则会发生未定义的行为。

因此,销毁线程需要等到所有其他线程完成退出屏障。为了实现这一点,需要额外的同步。 使用 pthread_cond 具有替代实现的源

在这个问题中,用户正在执行与您在示例代码中相同的逻辑。 https://groups.google.com/forum/#!topic/thread-sanitizer/81idLTirikQ

于 2019-10-07T06:55:05.243 回答