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开始等待,但它会永远等待。
当我想在不锁定互斥锁的情况下通知其他线程时,如何避免这种情况。
答案 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
变量代表)。这就是为什么你仍然需要一个额外的互斥锁的原因:条件变量本身的并发更改受到保护(例如,您可以同时从多个线程通知),而保持该状态的数据的更改不受保护。这就是条件变量通常与互斥锁配对的原因:条件变量表示状态发生变化,而互斥锁则保护状态不受竞争影响。
在某些情况下,您不需要状态的互斥锁(例如,如果您的标志是原子变量)。当您将无锁数据结构与条件变量混合时,通常会发生这种情况。这是一种气味。条件变量用于等待以获取特定条件,它们本质上始终是阻塞的。使用无锁数据结构,您可以表达您永远不想阻止的意图。将两者混合通常表明设计有缺陷。