赛博考古(3)MCS锁原论文伪代码详解

在上篇文章中,我们讲解了CLH锁作者给出的伪代码。这篇文章将讲解同为自旋锁MCS锁。

MCS锁出自一篇1991年的论文 由Mellor-Crummey J M, Scott M L两人提出。

在这片论文中,作者们提到

传统观点认为,忙等待同步引起的争用是大型共享内存多处理器中可扩展性和可接受性能的主要障碍。

我们提出相反的观点,并提出快速、简单的算法,用于无中心互斥、读写器中心和屏障同步。

在MCS锁提出之前,普通的自旋锁忙等的时候是需要消耗cpu并且众多线程去访问同一个共享变量,这样做会导致缓存中的共享变量的拷贝频繁失效,也就是文中提到的大型内存多处理器中可扩展性和可接受性能的主要障碍。

接下来让我们看一下论文中提出的MCS锁,分析MCS锁是如何缓解上面提出的问题。

论文中的伪代码如下:

类似的,该锁分为三个部分,锁定义以及获取锁和释放锁两个操作。我们用LOCK表示一个锁的指针,PROCESS和PROCESS2来表示两个争夺锁的线程。

画板

先来看获取锁操作:


先定义一个节点pred表示前继节点,然后将线程节点的next设置为nil,然后使用fatch_and_store(L,I)原语将,Lock设置为I,并且返回原来的值此时lock指向PROCESS节点,并且先前指向的nil值赋值给pred。接下来的判断发现pred为nil,说明锁目前在空闲状态,直接获取并且执行。

在这里插入图片描述

假设当PROCESS获取锁之后,PROCESS2也来获取锁,那么就会使得LOCK指向新入队的PROCESS2节点,然后判断前继为PROCESS节点自己并不是第一个节点,那么开始自旋,自旋监控的是自身的locked字段。自旋一直需要等到前继改变自己的locked字段才会停止

画板

继续看如何释放锁:

如果当前无后继节点,那么把LOCK使用CAS操作设置为nil即可。

如果有后继的话,直接将后继的locked字段变为false表示锁空闲,一直在自旋的自旋锁便会结束自旋开始。

从本文可以看到CLH队列和MCS队列最大的不同之处是自旋所监视的字段所在位置不同,CLH自旋监测的是前继节点的字段。MCS队列监视的是自身节点的字段。

引用文献:

Mellor-Crummey J M, Scott M L. Synchronization without contention[J]. ACM SIGPLAN Notices, 1991, 26(4): 269-278.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值