当前位置: 技术问答>linux和unix
看到线程的条件变量这部分时有些糊涂!
来源: 互联网 发布时间:2016-05-07
本文导语: 书上说: 条件变量必须和互斥锁配合起来使用,它用于等待,直到某一特定条件为真。对条件变量的cv_wait操作将使线程阻塞,直到所等的条件信号成立后,才能由cv_signal操作将其中的一个阻塞线程唤醒。cv_wait操作...
书上说:
条件变量必须和互斥锁配合起来使用,它用于等待,直到某一特定条件为真。对条件变量的cv_wait操作将使线程阻塞,直到所等的条件信号成立后,才能由cv_signal操作将其中的一个阻塞线程唤醒。cv_wait操作在阻塞线程前,将对相应的互斥锁执行开锁操作,并在返回前重新对互斥锁进行关锁操作。
请问:为什么cv_wait操作在阻塞线程前,将对相应的互斥锁执行开锁操作??
条件变量必须和互斥锁配合起来使用,它用于等待,直到某一特定条件为真。对条件变量的cv_wait操作将使线程阻塞,直到所等的条件信号成立后,才能由cv_signal操作将其中的一个阻塞线程唤醒。cv_wait操作在阻塞线程前,将对相应的互斥锁执行开锁操作,并在返回前重新对互斥锁进行关锁操作。
请问:为什么cv_wait操作在阻塞线程前,将对相应的互斥锁执行开锁操作??
|
这跟互斥锁的概念有关,一般来说,互斥锁所包含的代码段是不可重用的,也就是说同一时间只有一个进程能执行该代码段。
cv_wait的作用是条件阻塞当前线程,则势必需要将互斥锁代码段解锁以供别的线程使用(可理解为释放资源),否则会形成死锁,自己被阻塞而别的线程又无法继续执行。
反之cv_wait在条件满足唤醒当前线程之前,应该将互斥锁锁定以便执行该代码段(可理解为占有资源),同时别的进程将不能执行该代码段。
cv_wait的作用是条件阻塞当前线程,则势必需要将互斥锁代码段解锁以供别的线程使用(可理解为释放资源),否则会形成死锁,自己被阻塞而别的线程又无法继续执行。
反之cv_wait在条件满足唤醒当前线程之前,应该将互斥锁锁定以便执行该代码段(可理解为占有资源),同时别的进程将不能执行该代码段。
|
不开锁的话,另一个线程没法子进行cv_signal操作。
|
就用操作系统原理中常见的生产者-消费者问题来说:
consumer: 消费者
producer:生成者
number:产品数量
lock: 加锁
unlock: 解锁
wait: 等待
signal: 通知
首先,锁操作是保护number这个共享变量,条件变量的具体含义也是基于number,以下用伪码说明:
consumer: 消费者
producer:生成者
number:产品数量
lock: 加锁
unlock: 解锁
wait: 等待
signal: 通知
首先,锁操作是保护number这个共享变量,条件变量的具体含义也是基于number,以下用伪码说明:
consumer() {
while (1) {
lock /*为了检查共享变量number是否满足条件,要加锁*/
while ( number == 0 ) { /*实践中wait可能会由于中断或其它原因返回,如果是由这些异常导致则继续wait,如果确实number
> 0,进行循环后的处理*/
wait /*只有确定number等于零即没有产品时,才需要wait,否则就完全是浪费;进入wait和解锁是原子操作,是由系统保证
的,为什么要解锁?如果不解锁,producer怎么改变number让其大于零以达到signal的目的?不管何种原因wait返
回,都会先加锁再返回的,同样是原子操作,由系统保证,为什么加锁?如果不加锁怎么检查number的值?*/
}
number-- /*取出产品*/
unlock /*成功取出产品后尽快解锁,提高并发能力*/
/*消费中。。。*/
}
}
producer() {
while (1) {
/*生产中。。。*/
lock /*为了检查共享变量number是否满足条件,要加锁*/
number++ /*加入产品*/
if (number == 1) /*说明生产这个产品前number == 0, 可能有consumer在wait,需要我们signal*/
signal /*通知consumer*/
unlock /*成功放入产品后尽快解锁,提高并发能力*/
}
}