Chinaunix
标题:
条件变量为什么要用互斥锁来保护?
[打印本页]
作者:
hbmhalley
时间:
2011-12-03 18:22
标题:
条件变量为什么要用互斥锁来保护?
如果pthread_cond_wait只有cond*一个参数,pthread_cond_signal也只有cond*一个参数,一个用来等,一个用来唤醒,工作的也挺好的不是么?
所有书所有资料所有人都说“互斥锁用来保护条件变量”“防止竞争”等等,为什么要保护?防止什么竞争?这个mutex的作用到底是什么?如果所有使用pthread_cond_wait的地方mutex参数各不相同,那么这个mutex参数是不是就相当于没有用了?
谢谢!!
作者:
赤夜萌香
时间:
2011-12-03 18:26
个人理解走到pthread_cond_wait后,如果条件不满足
该线程就休眠了,等待条件满足后被唤醒。节省了线程不断运行浪费的资源
作者:
hbmhalley
时间:
2011-12-03 18:28
回复
2#
赤夜萌香
是啊是啊我的理解和你完全一样 但整个过程中和mutex有半毛钱关系么?? 晕死我了 ..
作者:
赤夜萌香
时间:
2011-12-03 18:30
有关系,pthread_cond_wait内需要写入mutex变量参数
作者:
hbmhalley
时间:
2011-12-03 18:35
回复
4#
赤夜萌香
= = 囧 我就是想问设计者为什么要额外加这么一个mutex参数?如果不加会出什么问题?那些所谓“竞争”“保护”指的是什么?
谢谢!
作者:
赤夜萌香
时间:
2011-12-03 18:39
这个解释起来,就涉及mutex了,你会用互拆锁的话,后面的应该也不难。
pthread_cond_wait他除了判断条件是否满足,还有控制mutex的功能,
如果不满足条件,他要先释放互拆锁,在进入睡眠中
作者:
赤夜萌香
时间:
2011-12-03 18:45
本帖最后由 赤夜萌香 于 2011-12-03 18:46 编辑
也不能说让pthread_cond_wait判断条件,这个条件还是编译者自己给的,
如一个while循环,循环里的条件不满足了,就不做pthread_cond_wait
满足就执行pthread_cond_wait,执行pthread_cond_wait就会进入睡眠,但是会在睡眠前先释放他控制的互拆锁
作者:
hbmhalley
时间:
2011-12-03 19:08
回复
6#
赤夜萌香
对,就是这里不明白。比如pthread_cond_wait (&COND , &MUTEX) ,那么这个函数只是简单地将三个类似 unlock(MUTEX), wait(COND), lock(MUTEX) 的函数原子地绑在一起而已么?如果是的话,那么这么做目的是什么?满足某个条件时也很有可能需要同时开始好多任务啊,为什么要强行lock掉呢?
作者:
赤夜萌香
时间:
2011-12-03 19:18
本帖最后由 赤夜萌香 于 2011-12-03 19:20 编辑
pthread_cond_wait,pthread_cond_signal
与pthread_mutex_lock,pthread_mutex_unlock;
是两部分,先有后者,后者使用上有不足处,故需要用前者来弥补。前者只是一个辅助弥补;
关键还是理解后者的用法,完全理解了,再去看前者是如何辅助lock与unlock的不足的;
如果还不能完全消化mutex部分就去看 cond会自然狠吃力,建议先完全理解mutex
作者:
hbmhalley
时间:
2011-12-03 19:37
回复
9#
赤夜萌香
多谢!好像明白了 .. 是不是因为mutex只有锁定与否,但继续运行的条件不只“mutex未锁”这么简单,所以用cond暂时阻塞并解锁以让出资源?
如果是这样,那么如果我想实现一个简单得多的功能:当变量x为0时继续运行,此时mutex还有用么?直接写成 while (x) wait(&cond)就可以了是么?
.. 也就是说 .. 条件变量从一开始就不是我所想象的那个用途么 ..
作者:
djsxut
时间:
2011-12-13 13:06
pthread_cond_wait里面的mutex作用APUE里面也有写,就是安全的把该线程安全加入到等待条件发生的队列上。
作者:
hbmhalley
时间:
2011-12-13 13:33
回复
11#
djsxut
明白了. 谢谢
作者:
bqq402
时间:
2011-12-13 15:50
啊是啊我的理解和你完全一样 但整个过程中和mutex有半毛钱关系么?? 晕死我了 ..
作者:
djsxut
时间:
2011-12-14 11:04
条件变量都用互斥锁进行保护,条件变量状态的改变都应该先锁住互斥锁,pthread_cond_wait需要传入一个已经加锁的互斥锁,该函数把调用线程加入等待条件的调用列表中,然后释放互斥锁,这是一个原子操作。可以消除条件发生和线程睡眠等待条件发生间的时间间隙。比如说如果没有互斥锁,那么线程先判断条件是否发生,如果没有发生,让线程睡眠继续等待。如果在判断是否发生和线程睡眠这个间隙条件发生了,这就会有问题。
作者:
hbmhalley
时间:
2011-12-14 12:12
回复
14#
djsxut
就是说
为了避免
因
条件判断语句 与 其后的正文或wait语句 之间的间隙
而产生的
漏判或误判
, 所以用一个mutex来保证: 对于某个cond的 包括(判断,修改)在内的任何有关操作 某一时刻只有一个线程在访问
也就是说 条件变量本身就是一个竞争资源,这个资源的作用是
对其后程序正文的执行权
,于是用一个锁来保护
可以这样理解么?
作者:
hbmhalley
时间:
2011-12-14 12:17
回复
14#
djsxut
但是 如果用mutex消除了**与**之间的间隙,那么broadcast是什么作用?任意一个wait返回之前都会把mutex给锁住啊
作者:
djsxut
时间:
2011-12-14 12:37
回复
16#
hbmhalley
嗯,差不多这样,我认为就是按照一定的规程来进行操作,所以这种机制才生效。broadcast唤醒所有阻塞在该条件变量上的线程,然后按照一定的调度机制,线程竞争,就好像这些线程一起调用pthread_mutex_lock一样,所以最终也只有一个能够获得锁资源然后返回。不能获得锁的继续等待。
作者:
hbmhalley
时间:
2011-12-14 14:35
回复
17#
djsxut
哦 ..
刚才不理解 既然有mutex限制cond,那么broadcast也只能唤醒一个阻塞的线程,和signal有什么区别?
现在好像理解了,signal唤醒cond队列中的一个线程,但broadcast唤醒队列中所有线程,只不过都因为阻塞在mutex上而没有工作而已,线程之后的走向就决定在mutex上而与cond无关了
作者:
djsxut
时间:
2011-12-14 18:10
回复
18#
hbmhalley
嗯。还有一点小区别,signal函数是唤醒至少一个线程,这是man pthread_cond_signal里说的。可以自己去man一下,然后去看看APUE。
作者:
madbunny
时间:
2016-04-28 18:32
因为没有锁,只有条件变量是保证不了资源的互斥访问的。
你看wait函数的用法,它阻塞结束之后就不管剩下的代码了。不像mutex前后包含一下,保证中间的代码可以安全的访问被保护的资源。
但是为什么一定要传进去一个mutex参数呢?因为实际上wait函数偷偷地unlock了穿进去的锁。
需要用到wait函数的都是消费者。条件变量需要保证生产者优先访问资源,生产者访问资源又必须要get锁,所以wait函数其实是把得到的锁unlock了。等到退出之前再重新尝试lock。
这样才可以保证资源可用的时候消费者可以安全访问,资源不可用的时候也不会被消费者锁住,生产者访问不到。
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2