我试图使用条件变量为线程实现屏障系统,但是有一个警告,即一旦屏障填满,第一个到达的线程必须写入资源以与其余线程共享。问题是,当我运行程序时,广播调用不会唤醒大多数线程,我花了很长时间试图调试它没有成功。
如果我删除了对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个线程。
由于
答案 0 :(得分:0)
您的代码中似乎有竞争条件。特别是,看起来你假设当一个线程从它的条件循环中醒来时,变量'group'将比它们进入时高一个,这并不总是正确的。想象一下,当你有非常“懒惰”的线程需要很长时间才能在发出信号后实际运行时会发生什么。当他们点击这一行时:
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。那么,为什么另一个线程呢呢呢?