c - 使用条件变量实现线程屏障会导致奇怪的行为

标签 c multithreading barrier

我正在尝试使用条件变量为线程实现屏障系统,但有一个警告,即一旦屏障填充,第一个到达的线程必须写入资源以与其余线程共享。问题是,当我运行程序时,广播调用不会唤醒大多数线程,我花了很长时间尝试调试它,但没有成功。

如果我删除了对 add_codeword() 的调用,那么线程就会完美地组合在一起,我怀疑这与 add_codeword() 包含大约 4 秒的等待有关。

void join_meetup(char *value, int len) {

pthread_mutex_lock(&mut);
if(++count < grp_size) {
    if(count == 1) {
        add_codeword(value, len);  //<=== This has a wait() all of 4 seconds.
    }

    int curr_group = group;
    while(curr_group == group) {
        pthread_cond_wait(&queue, &mut);
    }

}else{
    if(meet_ord == MEET_LAST) {
        add_codeword(value, len);
    }

    count = 0; //Reset group counter.
    group++; //Increment the group num

    pthread_cond_broadcast(&queue);

}

read_resource(&code_list[(group-1) % CODE_SIZE], value, len);
pthread_mutex_unlock(&mut);

}

以下是组大小设置为 3 的示例输出:

Group 1: 1
Group 1: 1
Group 1: 1
INISHED WRITING CODE! 4
Group 2: 4
INISHED WRITING CODE! 7
Group 3: 7
Group 3: 7
Group 3: 7
Group 4: 10
FINISHED WRITING CODE! 13
Group 4: 10
Group 4: 10
Group 5: 13
FINISHED WRITING CODE! 16
Group 5: 13
Group 5: 13
Group 5: 13
Group 5: 13

如您所见,组 2 只有 1 个线程,组 5 有 5 个线程。

谢谢

最佳答案

您的代码中似乎存在竞争条件。特别是,您似乎假设当线程从其条件循环中唤醒时,变量“group”将比它们进入时高1,但这并不总是正确的。想象一下,当您有非常“惰性”的线程,在收到信号后需要很长时间才能实际运行时,会发生什么。当他们到达这条线时:

read_resource(&code_list[(group-1) % CODE_SIZE], value, len);
与特定线程进入时相比,

“group”可能已被后续线程更新多次次。试试这个:

void join_meetup(char *value, int len) 
{
  pthread_mutex_lock(&mut);

  int my_group = group;

  if (++count < grp_size) 
  {
    if (count == 1)
        add_codeword(value, len);  //<=== This has a wait() all of 4 seconds.

    while (group == my_group)
        pthread_cond_wait(&queue, &mut);    
  }
  else
  {
    if (meet_ord == MEET_LAST)
        add_codeword(value, len);

    count = 0; //Reset group counter.
    group++;   //Increment the group num

    pthread_cond_broadcast(&queue);    
  }

  read_resource(&code_list[my_group % CODE_SIZE], value, len);
  pthread_mutex_unlock(&mut);
}

这应该确保线程获得其组所需的资源(忽略数组+模数的环绕)。当然,并不能真正保证他们醒来并继续他们正在做的其他事情的顺序。我也对这段代码表示怀疑:

    if (meet_ord == MEET_LAST)
        add_codeword(value, len);

因为看起来新组的第一个线程负责为该组执行 add_codeword 。那么,为什么另一个线程也在这样做呢?

关于c - 使用条件变量实现线程屏障会导致奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44599194/

相关文章:

c - 如何配置 git 以忽略文件?

c - 如何将掩码应用于 const void* 地址?

java - 从 Java 中的不同线程更新 GUI 的非马虎设计模式

android 持续轮询...如何?

c++ - 为什么 C++20 屏障中存在单独的到达和等待?

opencl - OpenCL 中的障碍

c - 重用现有的链表 API 实现

java - 同步块(synchronized block)无法正常工作

memory-management - 为什么我们不在用户空间使用屏障

在 FFmpeg 中正确分配和填充帧