信号量:
多个线程在读写某个共享数据(全局变量等)时必须通过某种方法实现共享数据的互斥访问或者同步访问(例如线程 B 等待线程 A 的结果以继续运行)。其中,信号量是一种最常见的方法。
信号量是一种约定机制:在共享资源的互斥访问中,它约定当一个线程获得信号量(Wait)后,其他线程不可以再次获得该信号量直到信号量被释放(Give);在同步机制中,它约定等待信号量(Take)的线程(或者说等待信号更确切)在收到信号量之前应该处于阻塞状态,直到其他线程发送该信号量(Post)。
通常情况,对信号量只能实施三种操作:创建一个信号量(Create)、等待信号量(Wait)或者挂起(Pend)、给信号量(Give)或者发送(Post)。操作系统应该包含一个等待信号量线程队列(用于存放等待信号量的线程),当信号量可以被获得时,操作系统依据某种策略从队列中选择一个可以获得信号量的线程以继续运行。
SylixOS 信号量包括四种类型:二进制信号量、计数型信号量、互斥信号量(简称互斥量)和读写信号量。相关信号量介绍:https://blog.csdn.net/liangren_/article/details/108494322
条件变量:
有十个线程(线程 A、线程 1...线程 9)和一个变量 V,线程 A 需要写变量 V,线程 1... 线程 9 需要读变量 V。
我们假设只有在变量 V 的值改变时,读者线程才需要读变量 V,在变量 V 的值不变时,读者线程需要阻塞。
读者线程阻塞前可能需要一种“判断”操作,判断变量 V 当前的值是否与上一次读到的值不一致;“判断”操作前需要加锁,如果一致那么读者线程需要阻塞,真正进入阻塞状态前读者线程又需要释放该锁,释放锁与阻塞需要是一个不可打断的原子操作。
我们可以想象一下释放锁与阻塞不是一个原子操作的情形,如果读者线程在释放锁与阻塞之间被线程 A 抢占了,毫无疑问,线程 A 可以成功获锁,线程 A 写变量 V,变量 V 的值改变了,但读者线程却阻塞了,显然读者线程丢失了一次对变量 V 值改变的响应!
同时在线程 A 写变量 V 后以广播的方式“通知”多个读者线程去读该变量。
我们需要一种新的线程间通信手段——条件变量来解决以上问题——释放锁与阻塞是一个原子操作和能以广播的方式“通知”多个读者线程。
条件变量是多线程间的一种同步机制,条件变量与互斥锁一起使用时,允许线程以无竞争的形式等待条件的发生。条件本身由互斥量保护,因此线程在改变条件之前必须首先锁住互斥量,其他线程在获得互斥量之前不会察觉到条件的改变。