并发-条件变量
2023-1-13
| 2023-8-2
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
在很多情况下,线程需要检查某一条件满足之后,才会继续运行。例如,父线程需要检查子线程是否执行完毕(这常被称为join())。这种等待如何实现呢?
期望能看到这样的输出:
可以尝试用一个共享变量
这种解决方案一般能工作,但是效率低下,因为主线程会自旋检查,浪费CPU 时间。我们希望有某种方式让父线程休眠,直到等待的条件满足(即子线程完成执行)。
 
线程可以使用条件变量(condition variable),来等待一个条件变成真。条件变量是一个显式队列,当某些执行状态(即条件)不满足时,线程可以把自己加入队列,等待(waiting)该条件。另外某个线程,当它改变了上述状态时,就可以唤醒一个或者多个等待线程(通过在该条件上发信号),让它们继续执行。Dijkstra 最早在“私有信号量”中提出这种思想。Hoare 后来在关于观察者的工作中,将类似的思想称为条件变量。
要声明这样的条件变量,只要像这样写:pthread_cond_t c;,这里声明 c 是一个条件变量(注:还需要适当的初始化)。条件变量有两种相关操作:wait()和 signal()。线程要睡眠的时候,调用 wait()。当线程想唤醒等待在某个条件变量上的睡眠线程时,调用 signal()
wait()调用有一个参数,它是互斥量。它假定在wait()调用时,这个互斥量是已上锁状态。wait()的职责是释放锁,并让调用线程休眠(原子地)。当线程被唤醒时(在另外某个线程发信号给它后),它必须重新获取锁,再返回调用者。这样复杂的步骤也是为了避免在线程陷入休眠时,产生一些竞态条件。
有两种情况需要考虑。第一种情况是父线程创建出子线程,但自己继续运行(假设只有一个处理器),然后马上调用thr_join()等待子线程。在这种情况下,它会先获取锁,检查子进程是否完成(还没有完成),然后调用wait(),让自己休眠。子线程最终得以运行,打印出“child”,并调用thr_exit()函数唤醒父进程,这段代码会在获得锁后设置状态变量done,然后向父线程发信号唤醒它。最后,父线程会运行(从wait()调用返回并持有锁),释放锁,打印出“parent:end”
第二种情况是,子线程在创建后,立刻运行,设置变量done 为1,调用signal 函数唤醒其他线程(这里没有其他线程),然后结束。父线程运行后,调用thr_join()时,发现done已经是1 了,就直接返回
 
 
 
  • 计算机基础
  • 操作系统
  • 并发-基于锁的并发数据结构并发-信号量
    目录