当前位置: 技术问答>linux和unix
问使用 posix 条件变量的问题
来源: 互联网 发布时间:2016-03-27
本文导语: 先贴一段代码: 1> pthread_mutex_t count_lock; 2> pthread_cond_t count_nonzero; 3> unsigned count; 4> 5> decrement_count() 6> { 7> pthread_mutex_lock(&count_lock); 8> while (count == 0) 9> pthread_cond_wait(&count_nonzero, &count_lock); 1...
先贴一段代码:
1> pthread_mutex_t count_lock;
2> pthread_cond_t count_nonzero;
3> unsigned count;
4>
5> decrement_count()
6> {
7> pthread_mutex_lock(&count_lock);
8> while (count == 0)
9> pthread_cond_wait(&count_nonzero, &count_lock);
10> count = count - 1;
11> pthread_mutex_unlock(&count_lock);
12> }
问题:1.当线程阻塞在cond_wait后,如果这时收到了cond_signal,它的状态即变为就绪态,等到CPU资源后就可以向下执行,并不是接收到signal后立即转为执行。其它线程也有可能先于它被唤醒,对count进行操作。这样理解对吗?
2.关于阻塞在cond_wait的线程,接收到cond_signal并且分到CPU后的执行顺序:
它是返回到第7行加锁,然后再执行第8行判断count是否为零呢,还是在cond_wait中自动完成加锁及判断条件?我试着在第8行和第9行之间加了一条print语句,线程被唤醒后并没有再次执行这条语句,说明再次锁mutex和条件判断是cond_wait自动完成的,那他是怎么知道判断条件的呢?
1> pthread_mutex_t count_lock;
2> pthread_cond_t count_nonzero;
3> unsigned count;
4>
5> decrement_count()
6> {
7> pthread_mutex_lock(&count_lock);
8> while (count == 0)
9> pthread_cond_wait(&count_nonzero, &count_lock);
10> count = count - 1;
11> pthread_mutex_unlock(&count_lock);
12> }
问题:1.当线程阻塞在cond_wait后,如果这时收到了cond_signal,它的状态即变为就绪态,等到CPU资源后就可以向下执行,并不是接收到signal后立即转为执行。其它线程也有可能先于它被唤醒,对count进行操作。这样理解对吗?
2.关于阻塞在cond_wait的线程,接收到cond_signal并且分到CPU后的执行顺序:
它是返回到第7行加锁,然后再执行第8行判断count是否为零呢,还是在cond_wait中自动完成加锁及判断条件?我试着在第8行和第9行之间加了一条print语句,线程被唤醒后并没有再次执行这条语句,说明再次锁mutex和条件判断是cond_wait自动完成的,那他是怎么知道判断条件的呢?
|
8> while (count == 0)
9> pthread_cond_wait(&count_nonzero, &count_lock);
上面的代码执行循序是:
先判断count == 0,如果为真,则执行pthread_cond_wait(),pthread_cond_wait()是一个阻塞的函数,直到pthread_cond_signal()来唤醒它。唤醒了之后这段代码就执行完了一次,此后就从头再来,继续判断,然后阻塞等待 。
我不知道这么说你明白没有。
BTW:顺便说一下昨天的一个 问题:
其它线程也有可能先于它被唤醒,对count进行操作。[不确定,好像现在的系统里已经屏蔽掉了“惊群”现象]
我刚才看了一下man pthread_cond_signal
DESCRIPTION
These functions shall unblock threads blocked on a condition variable.
The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond).
If more than one thread is blocked on a condition variable, the scheduling policy shall determine the order in which threads are unblocked. When each thread unblocked as a result of a pthread_cond_broadcast() or pthread_cond_signal() returns from its call to pthread_cond_wait() or pthread_cond_timedwait(), the thread shall own the mutex with which it called pthread_cond_wait() or pthread_cond_timedwait(). The thread(s) that are unblocked shall contend for the mutex according to the scheduling policy (if appli cable), and as if each had called pthread_mutex_lock().
The pthread_cond_broadcast() or pthread_cond_signal() functions may be called by a thread whether or not it currently owns the mutex that threads calling pthread_cond_wait() or pthread_cond_timedwait() have associated with the condition variable during their waits; however, if predictable scheduling behavior is required, then that mutex shall be locked by the thread calling pthread_cond_broadcast() or pthread_cond_signal().
The pthread_cond_broadcast() and pthread_cond_signal() functions shall have no effect if there are no threads currently blocked on cond.
红色标识就是所谓惊群现象。
蓝色标识就是说明多个线程被唤醒后调度的策略。
9> pthread_cond_wait(&count_nonzero, &count_lock);
上面的代码执行循序是:
先判断count == 0,如果为真,则执行pthread_cond_wait(),pthread_cond_wait()是一个阻塞的函数,直到pthread_cond_signal()来唤醒它。唤醒了之后这段代码就执行完了一次,此后就从头再来,继续判断,然后阻塞等待 。
我不知道这么说你明白没有。
BTW:顺便说一下昨天的一个 问题:
其它线程也有可能先于它被唤醒,对count进行操作。[不确定,好像现在的系统里已经屏蔽掉了“惊群”现象]
我刚才看了一下man pthread_cond_signal
DESCRIPTION
These functions shall unblock threads blocked on a condition variable.
The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond).
If more than one thread is blocked on a condition variable, the scheduling policy shall determine the order in which threads are unblocked. When each thread unblocked as a result of a pthread_cond_broadcast() or pthread_cond_signal() returns from its call to pthread_cond_wait() or pthread_cond_timedwait(), the thread shall own the mutex with which it called pthread_cond_wait() or pthread_cond_timedwait(). The thread(s) that are unblocked shall contend for the mutex according to the scheduling policy (if appli cable), and as if each had called pthread_mutex_lock().
The pthread_cond_broadcast() or pthread_cond_signal() functions may be called by a thread whether or not it currently owns the mutex that threads calling pthread_cond_wait() or pthread_cond_timedwait() have associated with the condition variable during their waits; however, if predictable scheduling behavior is required, then that mutex shall be locked by the thread calling pthread_cond_broadcast() or pthread_cond_signal().
The pthread_cond_broadcast() and pthread_cond_signal() functions shall have no effect if there are no threads currently blocked on cond.
红色标识就是所谓惊群现象。
蓝色标识就是说明多个线程被唤醒后调度的策略。
|
1:
1.当线程阻塞在cond_wait后,如果这时收到了cond_signal,它的状态即变为就绪态,等到CPU资源后就可以向下执行,并不是接收到signal后立即转为执行。 [理解OK]
其它线程也有可能先于它被唤醒,对count进行操作。[不确定,好像现在的系统里已经屏蔽掉了“惊群”现象]
2:
.关于阻塞在cond_wait的线程,接收到cond_signal并且分到CPU后的执行顺序:
是在cond_wait中自动完成加锁及判断条件
那他是怎么知道判断条件的呢?你这里的判断条件是指什么?
|
如果cond_wait都还没来得及执行,他怎么自动加锁呢?如果先于它被调度的一个线程锁了count并对其操作,count值在cond_wait醒来时不就被改变了吗?
我感觉你好像搞混了,在cond_wait之前count_lock已经锁住了:
在line7,line9(开区间)之间,count_lock是被锁住了的,其他线程拿不到这把锁也就改不了count
在line9 pthread_cond_wait执行期间, count_lock被解锁了,其他线程可以改变count
line9 pthread_cond_wait返回后,count_lock继续被锁,其他线程拿不到锁改不了count
我感觉你好像搞混了,在cond_wait之前count_lock已经锁住了:
在line7,line9(开区间)之间,count_lock是被锁住了的,其他线程拿不到这把锁也就改不了count
在line9 pthread_cond_wait执行期间, count_lock被解锁了,其他线程可以改变count
line9 pthread_cond_wait返回后,count_lock继续被锁,其他线程拿不到锁改不了count
|
Linux 下我认为是这样的:
pthread_mutex_lock(&count_lock); // count_lock 锁住
pthread_cond_wait(&count_nonzero, &count_lock); // 如果没有收到信号线程进入阻塞队列,该线程对count_lock解锁(内部实现)并进入Sleep状态,当收到signal信号后,对count_lock加锁,然后继续向后执行
pthread_mutex_unlock(&count_lock); // 解锁
在RedHat 9.0下面是这样的。而且当调用signal时,如果此时对条件变量count_nonzero阻塞的队列是空的,发送的信号还会丢失。
pthread_mutex_lock(&count_lock); // count_lock 锁住
pthread_cond_wait(&count_nonzero, &count_lock); // 如果没有收到信号线程进入阻塞队列,该线程对count_lock解锁(内部实现)并进入Sleep状态,当收到signal信号后,对count_lock加锁,然后继续向后执行
pthread_mutex_unlock(&count_lock); // 解锁
在RedHat 9.0下面是这样的。而且当调用signal时,如果此时对条件变量count_nonzero阻塞的队列是空的,发送的信号还会丢失。
|
PThreads Primer 一书中这样描述的:
?
lock-> cond -----> continue unlock
^ |
| |-------> unlock sleep lock -> |
| ^ |
---------------------|-----------|
|
|
|
lock-> cond = TRUE -> unlock ->wakeup -> continue
但我在RedHat 9.0 上测试了一下,感觉不像,不知道在其他平台上是什么样的,
大家可以在其他平台上测试 然后分享下结果。
?
lock-> cond -----> continue unlock
^ |
| |-------> unlock sleep lock -> |
| ^ |
---------------------|-----------|
|
|
|
lock-> cond = TRUE -> unlock ->wakeup -> continue
但我在RedHat 9.0 上测试了一下,感觉不像,不知道在其他平台上是什么样的,
大家可以在其他平台上测试 然后分享下结果。
|
pthread_cond_wait执行时,count_lock解锁,pthread_cond_wait返回前再自动加锁,所以描述1不可能,除非某处操作count前没有锁count_lock