MCS锁 简介

本文深入解析MCS锁的实现原理及Java代码实现。MCS锁由发明者姓名首字母命名,其特点在于节点自身判断是否获取锁。文章通过对比CLH锁,详细介绍了MCS锁的lock与unlock方法,并解释了等待队列的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

上一篇分析了CLH锁,这篇分析一下MCS锁。如果没有看过上一篇的话,建议先看一下 CLH锁简介,本篇是在上一篇的基础上做了简单的描述。

简述

MCS 的名字也是由发明人的名字字幕组合来的(John Mellor-Crummey and Michael Scott)。MCS与CLH最大的不同是,CLH在前驱节点上判断是否获得锁,MCS则是在自身的节点上判断是否能够获取到锁。

Java代码

public class MCSLock {

    public class QNode {
        volatile boolean locked = false;
        QNode next = null;
    }

    private AtomicReference<QNode> tail;
    private ThreadLocal<QNode> myNode;

    public MCSLock() {
        tail = new AtomicReference<QNode>(null);
        myNode = new ThreadLocal<QNode>() {
            protected QNode initialValue() {
                return new QNode();
            }
        };
    }

    public void lock() {
        QNode qnode = myNode.get();
        QNode pred = tail.getAndSet(qnode);
        if (null != pred) {
            qnode.locked = true;
            pred.next = qnode;
        }
        while (qnode.locked) {
        }
    }

    public void unlock() {
        QNode qnode = myNode.get();
        if (null == qnode.next) {
            if (tail.compareAndSet(qnode, null)) {
                return;
            }
            while (null == qnode.next) {
            }
        }
        qnode.next.locked = false;
        qnode.next = null;
    }
}

窥探原理

MCS同样有一个tail节点,也是存放最后一次申请锁的对象,另外它只有一个myNode属性。它的QNode对象内部除了维护一个boolean类型的locked变量,还有一个QNode类型的next变量,用来指向下一个节点。CLH锁等待队列是一个逻辑上的队列,而MCS锁的等待队列是一个显示的单向链表。

lock()

lock方法先将自身的locked属性设置为true,将tail节点上的对象的next变量设置为自己,然后在自身的locked变量上等待锁。

unlock()

unlock方法先判断后面有没有对象在等待获取锁,如果有的话将后面对象的locked变量设置为false,即通知后面的对象可以执行任务了,随即将自身的next至空(因为是ThreadLocal类型的变量,用完清理,在上一篇讲解CLH锁的时候有说明),如果后面没有对象在等待的话,将tail节点至空(这里是一个CAS操作),如果CAS至空操作失败,证明后面又有对象申明了锁,下面的 while(null == qnode.next) 循环则是为了确保后面的对象被成功加入到等待队列(链表)的保护工作。

 

 

转载于:https://my.oschina.net/u/232911/blog/3029625

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值