首页 > 解决方案 > 使用条件变量解锁一个线程但互斥锁不会导致死锁?

问题描述

基本问题,但为了简洁起见,我有两个线程在特定条件下bar解除阻塞foo,但即使程序运行良好令我惊讶的foo是,如果首先运行它会导致死锁,这意味着bar不应该鉴于条件变量永远不会为真,能否继续进行foo

pthread_mutex_t lock;
pthread_cond_t cv;
bool dataReady = false;

void foo(void *arg)
{
    printf ("Foo...\n");
    pthread_mutex_lock(&lock);
    
    while (!dataReady)
    {   
        pthread_cond_wait(&cv, &lock);
    }
    printf ("Foo unlocked...\n");
    dataReady = true;
    
    pthread_mutex_unlock(&lock);
}

void bar(void *arg)
{
   printf ("Bar...\n");
   pthread_mutex_lock(&lock);
   sleep(3);
   printf ("Data ready...\n");
   dataReady = true;
   pthread_cond_broadcast(&cv);
   
   pthread_mutex_unlock(&lock);
}

int main(void)
{

int main() 
{
    pthread_t t1,t2;
    pthread_create(&t1,NULL,foo,NULL);
    pthread_create(&t2,NULL,bar,NULL);
    
    
    pthread_join(t1,NULL);
    pthread_join(t2,NULL);
    
    return 0;
}

同样在这种情况下,使用信号量没有意义是吗?

标签: cmultithreadingposix

解决方案


pthread_cond_wait(&cv, &lock);调用时原子地释放互斥锁,唤醒时重新获取它。

man 3 pthread_cond_wait

这些函数以原子方式释放互斥体并导致调用线程阻塞条件变量 cond;atomically 这里的意思是“原子地相对于另一个线程访问互斥锁,然后是条件变量”。也就是说,如果另一个线程能够在即将阻塞的线程释放后获得互斥锁,那么该线程中对 pthread_cond_broadcast() 或 pthread_cond_signal() 的后续调用将表现得就好像它是在 about-- to-block 线程已阻塞。

成功返回后,互斥锁将被锁定并归调用线程所有。

恕我直言 C++ 文档包含更清晰的解释(我知道语言不同,但操作原理保持不变): https ://en.cppreference.com/w/cpp/thread/condition_variable

  1. 在用于保护共享变量的同一个互斥锁上获取 std::unique_lockstd::mutex
  2. 任何一个
    1. 检查条件,以防它已经更新并通知
    2. 执行 wait、wait_for 或 wait_until。等待操作以原子方式释放互斥体并暂停线程的执行。
    3. 当通知条件变量、超时到期或发生虚假唤醒时,线程被唤醒,互斥体被原子地重新获取。如果唤醒是虚假的,线程应该检查条件并继续等待。

推荐阅读