在pthread_cond_wait()之前检查标志

时间:2013-08-01 03:21:58

标签: c++ c multithreading concurrency

bool flag=false;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;

void function1()
{
    pthread_mutex_lock(&mutex);
    while(!flag)
    {
    //#2
        pthread_cond_wait(&cond,&mutex);
    }
    pthread_mutex_unlock(&mutex);
}

void function2()
{
    flag=true;
    pthread_cond_signal(&cond);
}

这是情况。两个线程:thread1和thread2分别在function1和function2上运行。

由于CPU计划,

thread1在#2处停止。

thread2开始执行并将标志更改为true。

thread1开始等待,但它会永远等待。

当我想在不锁定互斥锁的情况下通知其他线程时,如何避免这种情况。

2 个答案:

答案 0 :(得分:4)

这就是更新谓词(flag)时必须锁定互斥锁的原因。别无选择。

pthread_mutex_lock(&mutex);
flag = true;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

(如果需要,您可以在pthread_cond_signal()之后移动pthread_mutex_unlock()

答案 1 :(得分:1)

caf的回答已经说明了一切,但是让我在这里添加一个理由来解释为什么需要锁定,因为这可能会让人感到有些困惑。

从概念上讲,条件变量表示达到了所需的状态。它本身并不代表该状态(在您的情况下,状态由flag变量代表)。这就是为什么你仍然需要一个额外的互斥锁的原因:条件变量本身的并发更改受到保护(例如,您可以同时从多个线程通知),而保持该状态的数据的更改受保护。这就是条件变量通常与互斥锁配对的原因:条件变量表示状态发生变化,而互斥锁则保护状态不受竞争影响。

在某些情况下,您不需要状态的互斥锁(例如,如果您的标志是原子变量)。当您将无锁数据结构与条件变量混合时,通常会发生这种情况。这是一种气味。条件变量用于等待以获取特定条件,它们本质上始终是阻塞的。使用无锁数据结构,您可以表达您永远不想阻止的意图。将两者混合通常表明设计有缺陷。