什么'如果pthread_cond_wait自己这样做,那么锁定和解锁互斥锁的意义就在于什么
What's the point of locking and unlocking a mutex if pthread_cond_wait does that itself?
我试图了解互斥和条件变量之间的区别,但被下面的代码弄糊涂了。
// Lock mutex and then wait for signal to relase mutex
pthread_mutex_lock( &count_mutex );
/*Wait while functionCount2() operates on count
mutex unlocked if condition varialbe in functionCount2() signaled. <-- so then why call pthread_mutex_unlock() 3 lines latter if it's already unlocked?*/
pthread_cond_wait( &condition_var, &count_mutex );
count++;
printf("Counter value functionCount1: %dn",count);
pthread_mutex_unlock( &count_mutex );
根据文档pthread_cond_wait()
"原子释放互斥并导致调用线程阻塞条件变量",那么如果pthread_cond_wait()
只是解锁它,pthread_mutex_lock( &count_mutex );
有什么意义?既然pthread_cond_wait()
已经解锁了它,那么后者调用pthread_mutex_unlock()有什么意义呢?
对我来说,如果pthread_cond_wait()不接受互斥,这是有意义的,我认为这就是它的意义所在。
首先让我们定义一些可能有点混淆的术语:
-
condition:这是一个线程用来确定是否发生了什么事情或是否需要完成工作的表达式。例如,一个条件可能是队列不为空。
-
条件变量:这是pthread库(或类似库)提供的一个同步对象,用于让线程等待条件更改。一个线程可以"等待"一个条件变量,然后当另一个线程发出该条件变量的信号时,等待的线程将唤醒。
请注意,"条件"与"条件变量"是不同的。
当使用条件变量时,线程需要检查条件(无论是什么),然后如果条件不满足,它可以等待条件变量,直到有信号表明它应该再次检查条件。
然而,这一系列事件:
- 检查状况
- 等待条件变量
它本身并不是原子性的——如果在步骤1和步骤2之间,另一个线程发出条件变量的信号,那么等待的线程可能永远不会醒来(条件变量不记得过去发生过信号;当发出信号时,它们只会解锁已经在等待的线程)。为了避免这个问题,条件变量必须与确保这两个步骤相对于处理条件和条件变量的其他线程以原子方式发生的模式一起使用。这种模式是:
- 任何读取或更新条件中使用的对象的线程在执行此操作时都必须持有互斥对象。请注意,这包括可能等待条件变量的线程
- 在等待条件变量时,在持有互斥对象时检查条件的线程必须继续持有
pthread_cond_wait()
调用的互斥对象。这确保了上述步骤1和2之间的竞争条件不会发生,因为在pthread_cond_wait()
调用准备好线程等待之前,任何更新条件的东西都无法获取互斥。此时,pthread_cond_wait()
函数将释放互斥,这将允许更新线程获取互斥并更新条件
让我们看看以下两个函数,等待和通知。两者都在两个独立的线程中运行,并使用全局定义的变量value、mutex和cond。让我们假设等待线程首先启动并锁定互斥锁。现在可以安全地测试条件"值为零",因为锁保证没有其他线程可以更改值。在下一步中,我们的等待线程正在条件变量上等待通知函数的信号,即值已更改,应再次检查。
void* waiting(void* arg)
{
pthread_mutex_lock(&mutex);
while(value == 0)
{
pthread_cond_wait(&cond, &mutex);
}
printf("waiter %d releasesn", *tid);
pthread_mutex_unlock(&mutex);
}
现在让我们看看通知功能的作用。您还记得我们已经将互斥锁锁定在等待线程中吗?如果不释放它,我们的通知函数永远无法获得互斥并更改值。这就是pthread_cond_wait释放它的原因。不,函数不会最终释放它,只是在函数被阻塞的那段时间。现在,我们的通知线程可以更改值,并向pthread_cond_wait发送一个信号,表示发生了一些事情。当pthread_cond_wait解除锁定(返回)时,互斥锁将再次锁定!
void* notifying(void* arg)
{
pthread_mutex_lock(&mutex);
value = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
有趣的是,在循环中等待条件变量,反复检查条件是很常见的。为什么?有时pthread_cond_wait在没有从通知函数获得信号的情况下解除阻塞(所谓的杂散信号)。
- 我应该在锁定TBitmap画布后解锁它吗
- 虚假唤醒是否会解锁所有等待线程,甚至是不相关的线程?
- c++ 为什么我不应该从不同的线程解锁互斥锁
- 在新作用域中使用unique_lock是否等效于在使用共享资源的工作结束时解锁调用
- "data race"(不是真的)在通知条件变量并解锁关联的互斥锁后
- 程序输入密码并解锁窗口7,8,10
- 在通知之前完成手动解锁
- STD :: Mutex如何在不同的线程中解锁
- 如何使用单个解锁方法(可称为读取器或写入器)实现C++读写器锁?
- 如何在C 中自动汇总日志消息并自动解锁互斥X
- 如果我们已经手动解锁了unique_lock,那么破坏时会解锁吗?
- 正在解锁手动未定义/不良设计的锁定guard
- 从C 运行代码后解锁绑定(在R中)的问题
- 在功能返回之前,可以解锁Mutex会增加并发
- 当互斥锁解锁时,它会notify_all或notify_one
- 如何确保在C ++中解锁储物柜?哪种解决方案更好
- 我应该如何在一个功能中锁定wxMutex,并在另一个功能中将其解锁
- mutex::lock() 检查一次解锁状态是否已经被另一个线程锁定?
- 在Qt 5.4中可以对互斥对象进行两次解锁吗
- C++线程:等待condition_variable后无法解锁阵列中的互斥锁