下面我们研究如何为共享资源添加锁定.
我们的目的是使所有对共享资源的操作都是原子的, 也就是说, 在操作该共享资源的其他线程执行前, 本线程对该资源的整个操作就已经完成了. 对我们下面要说的内存泄露的举例来说, 需要确保当一个线程(如B)发现特定内存块需要分配时, 它拥有执行分配的执行权力, 并且需要在其他线程(如A, C, D...)执行同一测试之前完成这个工作.
为此, 我们必须建立临界区: 在任意时刻, 代码只能被一个线程执行.
2. 概念:
进入休眠: 当一个Linux进程到达某个时间点, 此时它不能进行任何处理时, 它将进入休眠状态(阻塞), 这将把CPU让给其他执行线程, 直到将来它能够继续完成自己的处理为止.
信号量: 一个信号量本质上是一个整数值, 它和一对函数联合使用, 这一对函数通常成为P和V, 也就是我们所说的P/V操作.
- 当一个进程希望进入临界区时, 对临界区的信号量执行P操作:
-
- 如果信号量的值大于0, 则该值会减1, 而进程可以继续;
-
- 如果信号量的值等于0(或更小), 进程必须等待直到其他人释放该信号量.
- 当一个进程完成对临界区的操作时, 对临界区信号量执行V操作:
-
- 将信号量的值加1, 并在必要时唤醒等待的进程.
- 在这种模式下, 一个信号量有时也称为一个"互斥体"(mutex), 它是互斥的简称.
3. 规则:
- 当信号量用于互斥时(即避免多个进程同时操作一个临界区), 信号量的值应该初始化为1.
- 信号量在任何时刻只能由单个进程或线程拥有.