自旋锁 (spin lock) 是一个典型的对临界资源的互斥手段,自旋锁是基于 CAS 原语的,所以它是轻量级的同步操作,它的名称来源于它的特性。自旋锁是指当一个线程尝试获取某个锁时,如果该锁已被其他线程占用,就一直循环检测锁是否被释放,而不是进入线程挂起或睡眠状态。由于自旋锁只不进行线程状态的改变(挂起线程),所以当线程竞争不激烈时,它的响应速度极快(因为避免了线程调度的上下文切换)。自旋锁适用于锁保护的临界区很小的情况,线程竞争不激烈的场景下。如果线程之间竞争激烈或者临界区的操作特别耗时,那么线程的自旋操作就会耗费大量的 cpu 资源,所以这种情况下性能就会下降明显。
这里用到了原子字段更新器,让 tail 变量可以具有 CAS 的功能,具体可以参考之前的文章 CAS 与原子变量
缺点
先说一下NUMA和SMP两种处理器结构 SMP(Symmetric Multi-Processor),即对称多处理器结构,指服务器中多个 CPU 对称工作,每个 CPU 访问内存地址所需时间相同。其主要特征是共享,包含对 CPU,内存,I/O 等进行共享。SMP 的优点是能够保证内存一致性,缺点是这些共享的资源很可能成为性能瓶颈,随着 CPU 数量的增加,每个 CPU 都要访问相同的内存资源,可能导致内存访问冲突,可能会导致 CPU 资源的浪费。常用的 PC 机就属于这种。
NUMA(Non-Uniform Memory Access) 非一致存储访问,将 CPU 分为 CPU 模块,每个 CPU 模块由多个 CPU 组成,并且具有独立的本地内存、I/O 槽口等,模块之间可以通过互联模块相互访问,访问本地内存的速度将远远高于访问远地内存(系统内其它节点的内存)的速度,这也是非一致存储访问 NUMA 的由来。NUMA 优点是可以较好地解决原来 SMP 系统的扩展问题,缺点是由于访问远地内存的延时远远超过本地内存,因此当 CPU 数量增加时,系统性能无法线性增加。
CLH 锁的缺点是在 NUMA 系统结构下性能很差,在这种系统结构下,每个线程有自己的内存,如果前趋结点的内存位置比较远,自旋判断前趋结点的 locked 域,性能将大打折扣,在 SMP 架构下能够保证内存一致性所以自旋判断较快
MCS 锁
MCS Spinlock 是一种基于显式链表(节点里面拥有 next 指针)的可扩展、高性能、公平的自旋锁,申请线程只在本地变量上自旋,由直接前驱负责通知其结束自旋(与 CLH 自旋锁不同的地方,不在轮询前驱的状态,而是由前驱主动通知),从而极大地减少了不必要的处理器缓存同步的次数,降低了总线和内存的开销。而 MCS 是在自己的结点的 locked 域上自旋等待。正因为如此,它解决了 CLH 在 NUMA 系统架构中获取 locked 域状态内存过远的问题。