我测试了在多线程代码中打印偶数/奇数的两个非常简单的例子,一个使用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()中幕后还有其他什么可以帮助吗?
由于
答案 0 :(得分:2)
两个代码段都有同样的问题。两个版本都有竞争条件。您正在关键部分之外阅读count
,其他线程可能会在此期间修改count
。
您恰好注意到没有条件变量的版本。
不是为循环条件读取count
,而是可以使用每个线程的本地标志,并在循环内更改它以打破循环。
类似的东西:
void *even(void *arg)
{
int flag = 1;
while(flag) {
pthread_mutex_lock(&mutex);
while(count % 2 != 0) {
pthread_cond_wait(&cond, &mutex);
}
printf("%d ", count++);
if (count >MAX) flag = 0;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
pthread_exit(0);
}
void *odd(void *arg)
{
int flag = 1;
while(flag) {
pthread_mutex_lock(&mutex);
while(count % 2 != 1) {
pthread_cond_wait(&cond, &mutex);
}
printf("%d ", count++);
if (count >MAX) flag = 0;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
pthread_exit(0);
}