【发布时间】:2015-07-07 09:17:05
【问题描述】:
我测试了两个在多线程代码中打印偶数/奇数的非常简单的示例,一个使用 pthread_cond_t,另一个不使用。
void *even(void *arg)
{
while(count < MAX)
{
pthread_mutex_lock(&mutex);
if(count % 2 == 0)
printf("%d ", count++);
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}
void *odd(void *arg)
{
while(count < MAX)
{
pthread_mutex_lock(&mutex);
if(count % 2 == 1)
printf("%d ", count++);
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}
void *even(void *arg)
{
while(count < MAX) {
pthread_mutex_lock(&mutex);
while(count % 2 != 0) {
pthread_cond_wait(&cond, &mutex);
}
printf("%d ", count++);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
pthread_exit(0);
}
void *odd(void *arg)
{
while(count < MAX) {
pthread_mutex_lock(&mutex);
while(count % 2 != 1) {
pthread_cond_wait(&cond, &mutex);
}
printf("%d ", count++);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
pthread_exit(0);
}
以上两个代码的行为不同。 第一个代码输出:
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9
第二个代码输出:
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9 10
第一个代码输出不一致的原因可能是:
在偶数线程中的以下调用之间:假设 count == 8
pthread_mutex_unlock(&mutex);
..... --> here, the odd thread increments the count by one before this thread could check the the following while condition
while(count < MAX)
所以偶尔会错过 10 个。
但是对于使用 pthread_cond_wait() 的代码,没有这样的不一致,虽然,同样的论点也可以: 在偶数线程中的这些调用之间:假设 count == 8
pthread_cond_signal(&cond);// mutex is already unlocked before condition is signaled.
.... --> here, the odd thread can increment the count to 10 before the even thread could check the while condition
while(count < MAX)
但在实践中,这从未发生在第二个代码中,所以不知何故,pthread_cond_wait() 代码处理了这种不一致,但我似乎不清楚如何处理?
在 pthread_cond_wait() 的幕后还有什么可以帮助的吗?
谢谢
【问题讨论】:
-
您实际上可以在 释放互斥锁之前发出条件信号...以避免您提到的那种竞争。
-
MAX常量的值是多少?看起来,它是 10,所以两种变体都会产生(通常)不正确的输出:它应该是 0...9。 -
是的,MAX定义为10。
-
@Dmitri 我认为,如果我发出条件信号,在释放互斥锁之前,竞争将更有可能。因为等待线程(奇线程)会醒来,并为互斥锁而战,一旦它获得锁,它就会增加计数,并且很有可能在偶数线程可以检查计数之前发生这种情况。
-
锁定互斥锁before循环,解锁after(在循环内都不做)...然后每个线程只能持有互斥锁当另一个线程正在等待时,如果不持有互斥锁,两者都不会读/写
count。
标签: c multithreading pthreads race-condition