ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

「并发原理专题」AQS的技术体系之CLH、MCS锁的原理及实现,java架构和java开发

2021-11-18 14:00:34  阅读:191  来源: 互联网

标签:node Node CLH java locked public 线程 原理 节点


  • 在SMP架构下,CLH更具有优势。

  • 在NUMA架构下,如果当前节点与前驱节点不在同一CPU模块下,跨CPU模块会带来额外的系统开销,而MCS锁更适用于NUMA架构。

加锁逻辑

1.获取当前线程的锁节点,如果为空,则进行初始化;

2.同步方法获取链表的尾节点,并将当前节点置为尾节点,此时原来的尾节点为当前节点的前置节点。

3.如果尾节点为空,表示当前节点是第一个节点,直接加锁成功。

  1. 如果尾节点不为空,则基于前置节点的锁值(locked==true)进行自旋,直到前置节点的锁值变为false。

解锁逻辑

  1. 获取当前线程对应的锁节点,如果节点为空或者锁值为false,则无需解锁,直接返回

  2. 同步方法为尾节点赋空值,赋值不成功表示当前节点不是尾节点,则需要将当前节点的locked=false解锁节点。如果当前节点是尾节点,则无需为该节点设置。

public class CLHLock {

private final AtomicReference tail;

private final ThreadLocal myNode;

private final ThreadLocal myPred;

public CLHLock() {

tail = new AtomicReference<>(new Node());

myNode = ThreadLocal.withInitial(() -> new Node());

myPred = ThreadLocal.withInitial(() -> null);

}

public void lock(){

Node node = myNode.get();

node.locked = true;

Node pred = tail.getAndSet(node);

myPred.set(pred);

while (pred.locked){}

}

public void unLock(){

Node node = myNode.get();

node.locked=false;

myNode.set(myPred.get());

}

static class Node {

volatile boolean locked = false;

}

}

MCS锁

MSC与CLH最大的不同并不是链表是显示还是隐式,而是线程自旋的规则不同:CLH是在前趋结点的locked域上自旋等待,而MCS是在自己的结点的locked域上自旋等待。正因为如此,它解决了CLH在NUMA系统架构中获取locked域状态内存过远的问题 。

MCS锁具体实现规则:

  • a. 队列初始化时没有结点,tail=null

  • b. 线程A想要获取锁,将自己置于队尾,由于它是第一个结点,它的locked域为false

  • c. 线程B和C相继加入队列,a->next=b,b->next=c,B和C没有获取锁,处于等待状态,所以locked域为true,尾指针指向线程C对应的结点

  • d. 线程A释放锁后,顺着它的next指针找到了线程B,并把B的locked域设置为false,这一动作会触发线程B获取锁。

public class MCSLock {

private final AtomicReference tail;

private final ThreadLocal myNode;

public MCSLock() {

tail = new AtomicReference<>();

myNode = ThreadLocal.withInitial(() -> new Node());

}

public void lock() {

Node node = myNode.

【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】

开源分享完整内容戳这里

get();

Node pred = tail.getAndSet(node);

if (pred != null) {

node.locked = true;

pred.next = node;

while (node.locked) {

}

}

}

public void unLock() {

Node node = myNode.get();

if (node.next == null) {

if (tail.compareAndSet(node, null)) {

return;

}

while (node.next == null) {

}

}

node.next.locked = false;

node.next = null;

}

class Node {

volatile boolean locked = false;

Node next = null;

}

public static void main(String[] args) {

MCSLock lock = new MCSLock();

Runnable task = new Runnable() {

标签:node,Node,CLH,java,locked,public,线程,原理,节点
来源: https://blog.csdn.net/m0_64205605/article/details/121399049

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有