【问题标题】:using pthread_cond_t and pthread_mutex_t使用 pthread_cond_t 和 pthread_mutex_t
【发布时间】: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


【解决方案1】:

两个代码 sn-ps 都有同样的问题。两个版本都有竞态条件。您正在临界区之外阅读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);
}

【讨论】:

    猜你喜欢
    • 2012-01-11
    • 2021-12-28
    • 2016-09-03
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多