并发编程 TSL指令 CAS

我们前面提供了一种避免竞态条件的方案:锁变量。

通过设置一个锁标志位,将其初始值设置为 0 ,当一个进程想进入临界区时,先检查锁的值是否为 0,如果为 0,则设置为 1,然后进入临界区,退出临界区后把锁的值改为0;若检查时锁的值已经为1,那么代表其他进程已经在临界区中了,于是进程进行循环等待,并不断检测锁的值,直到它变为0。

但这种方式本身就存在着竞态条件,原因是,当一个进程读出锁的值为0时,在它将其值设置为1之前,另一个进程被调度起来,它也读到锁的值为0,这样就出现了两个进程同时都在临界区的情况。

锁变量方案的致命的缺点是对状态变量进行改变的时候,如从 0 改为 1 或者从 1 改为 0 时,是可以被中断打断的,因此存在竞态条件。

假如在硬件 CPU 的支持下,保证锁变量的改变不被打断,那么锁变量成为一种很好的解决进程互斥的方法。

实际上,目前大多数的计算机的 CPU,都支持 TSL 指令,其全称为 Test and Set Lock,它将一个内存的变量(字)读取寄存器 RX 中,然后再该内存地址上存一个非零值,读取操作和写入操作从硬件层面上保证是不可打断的,也就是说是原子性的。它采用的方式是在执行 TSL 指令时锁住内存总线,禁止其它 CPU 在 TSL 指令结束之前访问内存。

TSL 指令也是我们常说的 CAS (Compare And Swap)。

什么是 CAS?CAS 即 Compare And Swap,先比较后交换的机制。

CAS 操作最终会翻译为在 CPU 上会执行 LOCK CMPXCHG 指令。从上层使用的角度来看,这是一个原子操作,中间不可中断。

什么是原语?内核提供给核外调用的过程或者函数成为原语(primitive),原语在执行过程中不允许中断。计算机进程的控制通常由原语完成。所谓原语,一般是指由若干条指令组成的程序段,用来实现某个特定功能,在执行过程中不可被 ...