【问题标题】:Does calling pthread_cond_wait in a thread unlock the mutex在线程中调用 pthread_cond_wait 是否会解锁互斥锁
【发布时间】:2020-12-12 09:47:09
【问题描述】:

手册页说这个 pthread_cond_wait 以原子方式解锁互斥锁(根据 pthread_unlock_mutex)并等待条件变量 cond 发出信号
但随后线程 start_function 可能被任何其他线程进入,导致两个线程处于关键块中。

    void* start_function(){
         pthread_mutex_lock(&mutex);
         // critical block
         pthread_mutex_unlock(&mutex);
    }
    
    int main(){
// code to create threads
        pthread_cond_wait(&cond, &mutex);
    }
    

所以在上面的代码中,当它点击 pthread_cond_wait 之后,它会解锁互斥锁?

【问题讨论】:

  • 这是未定义的行为。互斥锁必须由调用 pthread_cond_wait 的线程完全锁定,以防止出现不可预知的结果。
  • 这就是解锁的重点,它允许其他人访问与互斥锁关联的资源。

标签: c multithreading pthreads mutex


【解决方案1】:

创建线程时不需要有条件。在互斥中,一次只有一个进程可以运行临界区。一个进程在有限时间内保持在临界区,当它完成工作并且没有一个进程留在关键区域然后带有条件信号,另一个线程也准备好运行这个关键区域。所有这些工作都是为了避免僵局。此外,当进程在关键块之外停止时,它不能与其他进程交互。所以你的例子必须是:

void* start_function(){
         pthread_mutex_lock(&mutex);
           pthread_cond_wait(&cond, &mutex);
         // critical block or critical area

         // you can use signals here 
         pthread_mutex_unlock(&mutex);
    }
    
    int main(){
        // code to create threads
        for(int i=0;i<10;i++){
             pthreaf_create(x[i],&start_function,...,NULL);
       }
    }

可能是在程序结束时,一些 pthread 被卡在了 con_wait() ,所以你需要一个 broadcast() 来释放所有线程

【讨论】:

  • 所以在你发布的上述代码中。当 pthread_cond_wait 被执行时。互斥锁将被解锁。那么其他线程可以进入临界区吗?我明白为什么我的代码错误了,因为调用 _wait 的线程应该锁定互斥体
  • @pensee 没错。这对你有帮助吗?
  • 是的,这很有帮助。但我无法理解为什么在 pthread_cond_wait 上解锁互斥锁。 1) 那里没有 pthread_mutex_unlock 函数用于解锁。
    2) 如果 pthread_cond_wait() 释放锁并且在 pthread_mutex_lock(&mutex); pthread_cond_wait(&cond, &mutex); 之间有一段关键代码段,则可能麻烦,因为其他线程可能进入临界区。我可能很困惑。请纠正我。你怎么想
  • @pensee pthread_cond_wait 在它休眠之前解锁互斥锁(正如你注意到的),但是当它发出信号时,它会在它唤醒之前重新获取互斥锁(这可能需要等待)。因此,如果信号线程持有互斥锁(通常情况下),等待线程将不会继续,直到信号线程也解锁互斥锁。互斥锁锁定关键区域,但它可能会捕获信号并开始运行,因此您使用 cond 来为此
【解决方案2】:

手册页说这个 pthread_cond_wait 原子地解锁互斥锁 (根据 pthread_unlock_mutex)并等待条件变量 cond 发出信号

是的,就在他们说那个功能之后

应在调用线程锁定互斥锁的情况下调用或未定义的行为结果。

(强调添加)。你继续说,

但是线程 start_function 可能是 由任何其他线程进入导致两个线程处于关键状态 块。

如果您通过调用pthread_cond_wait() 而不持有指定的互斥锁来调用未定义的行为,那么任何事情 都可能发生——该行为是未定义的。未定义的行为可能只是简单地表现为两个线程同时在临界区中执行,可能会产生任何后续影响,但也有可能程序崩溃,然后或稍后,或损坏内存,或者死锁,或者在推特上发布你所有的密码,在各种可能性中。

所以在上面的代码中,当它点击 pthread_cond_wait 之后,它会解锁互斥锁?

不能说。同样,行为未定义。

【讨论】:

    猜你喜欢
    • 2010-11-22
    • 2013-02-02
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多