为什么调用pthread_cond_wait之前要先加锁

声明:本文程序截图自北京大学操作系统慕课的课件,图片下方的文字是图片内容所对应的慕课的章节

下面的程序是一个:使用pthread线程库解决生产者消费者问题(缓冲区的容量是1)的例子
在这里插入图片描述

(6.5节 pthread中的同步机制)

我们知道pthread_cond_wait上来做的第一件事就是:解锁。对于生产者来说在这个加锁与解锁之间被保护起来的临界区就是:while(buffer!=0);
为啥要保护这条判断语句呢?
我们可以考虑 如果调用pthread_cond_wait之前不加锁会可能会出现什么情况:

生产者发现buffer!=0,即缓冲区不为空,也就是没有地方放自己生产的产品,那么调用pthread_cond_wait,在生产者执行pthread_cond_wait的过程中,中断发生了,但此时生产者还没被放到等待队列中,之后消费者占据了处理机,消费了产品,改变了buffer的值,然后调用pthread_cond_signal,但这个时候没有生产者在等待队列上等待啊。发现问题了吧

在《unix高级环境编程》中有这样的描述:

The mutex passed to pthread_cond_wait protects the condition.The caller passes it locked to the function, which then atomically places them calling thread on the list of threads waiting for the condition and unlocks the mutex. This closes the window between the time that the condition is checked and the time that the thread goes to sleep waiting for the condition to change, so that the thread doesn’t miss a change in the condition. When pthread_cond_wait returns, the mutex is again locked

我们重点关注一下加粗的那句话,这句话说:因为这个操作关闭了两个时间节点之间的窗口,一个时间节点是:“条件已经被检查过了”,另一个时间节点是:“线程睡眠,等待条件改变”,所以线程不会错过条件的改变。

换句话说,调用pthread_cond_wait之前要先加锁是为了保护条件变量

我们不妨来对比一下使用PV操作解决生产者消费者问题的情况
在这里插入图片描述

(5.7节 生产者消费者问题)

这里我们是先对条件变量进行P操作再加锁
yi?刚才不说了得先加锁吗,那这样做不会出问题吗?

注意刚才可能出现的错误发生在:判断完条件与线程阻塞之间。而我们的P操作是原子操作,是不能被打断的。也就是说判断完条件后,如果条件不满足那线程等待,这两步之间不能被打断,所以进入等待之前,条件一定是不满足的,当条件满足时它将被唤醒。
这里我们本使临界区尽可能短的原则把锁放在了后面。

扫描二维码关注公众号,回复: 12421647 查看本文章

回到第一个程序,假设我们把 while(buffer!=0)和 pthread_cond_wait 这两个操作 作为一个整体 并弄成原子操作的话,我们就可以把锁放到pthread_cond_wait后面啦。当然这个是很难实现的,所以我们只能把锁放到前面。

湫某讲清楚了吧(唐叔腔)

感谢csdn博主:v-code 的这篇文章:多线程:pthread_cond_wait 实现原理 给了我灵感,本文中的那段英文也是在这篇文章中看到的。

猜你喜欢

转载自blog.csdn.net/weixin_42378324/article/details/108943460