0%

《操作系统》Linux 之锁

在当前的多核时代,多个线程可以分别处于一个处理器并行执行,我们知道一个进程中的全局变量是可以被线程共享的,如果两个并行线程同时对其读写,必然会出现数据错误

所以需要对这个全局变量加锁。常见有以下机制

多元信号量(Semaphone)

对于允许多个线程并发读写的资源,多元信号量是一个很好的选择。

一个初始值为 N 的多元信号量最多能允许 N 个线程并发读写(理解为初始值为 N 的多元信号量具有 N 个办法给线程的资源访问的许可证以及无数的假证书,信号量的值为 -2 说明真证书发放完毕,发了 N 个,还发了 2 个假证书,有两个线程正在等待)

每个线程访问资源时做如下操作

  1. 多元信号量的值原子性减一(向信号量申请访问证书)
  2. 如果信号量的值小于 0 (说明没有了真证书,开始发放假证书),则代表申请到了假证书,进入等待队列,否则代表获取了真证书,继续执行访问资源的操作
  3. 完事后,信号量原子性加 1(归还真证书)
  4. 如果信号量的值小于 1 (说明有线程拿着假证书在等待),则唤醒一个

二元信号量(Binary Semaphone)

二元信号量就是 N=1 的多元信号量。Golang 中的 Mutex 就是针对协程的类似实现

互斥量(Mutex)

和二元信号量很类似,唯一的不同是:

二元信号量可以由线程 a 获取,然后由线程 b 释放

而互斥量如果由线程 a 获取,那么必须由线程 a 释放

互斥量比二元信号量更严格

临界区(Critical Section)

临界区比互斥量还要严格,互斥量和二元信号量对所有线程都是可见的,也就是说

一个线程创建了一个互斥量或二元信号量,其他线程都可以尝试去获取这个互斥量或二元信号量

但是,临界区的可见度仅限于本进程,其他进程看不见

读写锁

对于一个共享资源,允许多个线程同时读取,不允许一读一写或者同时读,这个时候就可以使用读写锁机制。Golang 中的 RWLock 就是针对协程实现的这类机制

条件变量

跟多元信号量一样,一个共享资源可以被多个线程等待

使用条件变量可以让许多线程一起等待某事件的发生,当事件发生时(条件变量被唤醒),所有线程一起恢复执行




微信关注我,及时接收最新技术文章