CLH(Craig, Landin, and Hagersten locks):

  1. 是一个自旋锁,能确保无饥饿性,提供先来先服务的公平性。
  2. CLH锁也是一种基于链表的可扩展、高性能、公平的自旋锁,申请线程只在本地变量上自旋,它不断轮询前驱的状态,如果发现前驱释放了锁就结束自旋。
  3. AQS就是基于CLH队列,AQS是将每一条请求共享资源的线程封装成一个CLH锁队列的一个结点(Node),来实现锁的分配。
    当一个线程需要获取锁时:
1 创建一个的QNode,将其中的locked设置为true表示需要获取锁
2.线程对tail域调用getAndSet方法,使自己成为队列的尾部,同时获取一个指向其前趋结点的引用myPred
3.该线程就在前趋结点的locked字段上旋转,直到前趋结点释放锁
4.当一个线程需要释放锁时,将当前结点的locked域设置为false,同时回收前趋结点
如下图,线程A需要获取锁,其myNode域为true,tail指向线程A的结点,然后线程B也加入到线程A后面,tail指向线程B的结点。然后线程A和B都在其myPred域上旋转,一旦它的myPred结点的locked字段变为false,它就可以获取锁。明显线程A的myPred locked域为false,此时线程A获取到了锁。

public class CLHLock implements Lock {  AtomicReference<QNode> tail ;  ThreadLocal<QNode> myPred;  ThreadLocal<QNode> myNode;  public CLHLock() {  tail = new AtomicReference<QNode>(new QNode());  myNode = new ThreadLocal<QNode>() {  protected QNode initialValue() {  return new QNode();  }  };  myPred = new ThreadLocal<QNode>() {  protected QNode initialValue() {  return null;  }  };  }  @Override  public void lock() {  QNode qnode = myNode.get();  qnode.locked = true;  QNode pred = tail.getAndSet(qnode);  myPred.set(pred);  while (pred.locked) {  }  }  @Override  public void unlock() {  QNode qnode = myNode.get();  qnode.locked = false;  myNode.set(myPred.get());  }
}

CLH分析

CLH队列锁的优点是空间复杂度低(如果有n个线程,L个锁,每个线程每次只获取一个锁,那么需要的存储空间是O(L+n),n个线程有n个myNode,L个锁有L个tail),CLH的一种变体被应用在了JAVA并发框架中(AbstractQueuedSynchronizer.Node)。CLH在SMP系统结构下该法是非常有效的。但在NUMA系统结构下,每个线程有自己的内存,如果前趋结点的内存位置比较远,自旋判断前趋结点的locked域,性能将大打折扣。

一种解决NUMA系统结构的思路是MCS队列锁

MSCCLH最大的不同并不是链表是显示还是隐式,而是线程自旋的规则不同: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获取锁

转自

CLH(Craig, Landin, and Hagersten locks)机制相关推荐

  1. CLH锁 、MCS锁

    一. 1.SMP(Symmetric Multi-Processor) SMP(Symmetric Multi-Processing)对称多处理器结构,指服务器中多个CPU对称工作,每个CPU访问内存 ...

  2. Java 中的各种锁及其原理

    文章目录 概览 Synchronized锁 Synchronized 锁的底层类别 不同锁下对象头中的内容 偏向锁 轻量级锁 轻量级锁加锁过程 字节码层面 synchronized关键字最主要的三种使 ...

  3. java队列加锁_java并发-----浅析ReentrantLock加锁,解锁过程,公平锁非公平锁,AQS入门,CLH同步队列...

    前言 为什么需要去了解AQS,AQS,AbstractQueuedSynchronizer,即队列同步器.它是构建锁或者其他同步组件的基础框架(如ReentrantLock.ReentrantRead ...

  4. 并发编程面试题(2021最新版)

    目录 基础知识 并发编程的优缺点 为什么要使用并发编程(并发编程的优点) 并发编程有什么缺点 并发编程三要素是什么?在 Java 程序中怎么保证多线程的运行安全?并发编程三要素(线程的安全性问题体现在 ...

  5. Java并发编程面试题(2020最新版)

    转载自  Java并发编程面试题(2020最新版) 基础知识 并发编程的优缺点 为什么要使用并发编程(并发编程的优点) 充分利用多核CPU的计算能力:通过并发编程的形式可以将多核CPU的计算能力发挥到 ...

  6. 05.抽象队列同步器AQS应用之Lock详解

    AQS应用之Lock Java并发编程核心在于java.concurrent.util包而juc当中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列.条件队列.独占获取.共享获取等,而这个行为 ...

  7. 并发容器J.U.C -- AQS组件(一)

    AQS简介 AQS全名:AbstractQueuedSynchronizer,是并发容器J.U.C(java.lang.concurrent)下locks包内的一个类.它实现了一个FIFO的队列.底层 ...

  8. 面试官:多线程硬核50问!能回答一半就让你过

    前言 金九银十快要来了,整理了50道多线程并发面试题,大家可以点赞.收藏起来,慢慢品!~ 1.为什么要使用多线程 选择多线程的原因,就是因为快.举个例子: 如果要把1000块砖搬到楼顶,假设到楼顶有几 ...

  9. 一文让你彻底了解多线程

    伙伴们很抱歉,因为最近需要粉丝突破1000,所以很多文章都设置了仅粉丝可见,如果大家看完这篇文章感觉对自己没啥帮助,可以在取消关注!!! 本文篇幅很长,建议大家分段阅读,如果你准备面试,那么就请你一定 ...

  10. java个人整理知识点

    发展: 1.SE 标准版. 2.EE 企业版,基于SE. 3.ME 已经淘汰. JDK.JRE和JVM: JDK: 称为Java开发工具包( Java Development Kit).Java开发人 ...

最新文章

  1. Spring整合JMS(四)——事务管理
  2. PSXDMS cassandra testing
  3. 使用WebClient 获得网页内容或提交请求
  4. Zookeeper_简介
  5. AWS public key的邮件验证方式
  6. Java注解原理学习之@Cacheable debug
  7. 什么是mysql事物定义_Mysql事务原理
  8. python网站后台_Python 网站后台扫描脚本
  9. python后端面试题
  10. “云”话数字经济:2020 腾讯全球数字生态大会定档 9 月!​
  11. 【C++笔记】构造函数与析构函数相关知识
  12. IcedTea6 1.7.6、1.8.3和1.9.2补丁程序信息泄漏
  13. [RK3288][Android6.0] Audio中的HW Params设置流程
  14. 插入移动硬盘提示格式化怎么办?数据还有机会找回吗
  15. 字体 流光css,实例详解CSS3制作文字流光渐变特效
  16. 2022年~全网最真实的软件测试面试题合集
  17. 五年了还在原地踏步咋整?技术大佬给你整理了一套切实可行的方法论
  18. yolov8 做图片分类和 ResNet Efficientnet 等常用分类网络的对比
  19. 北邮邮箱配置客户端教程(如Windows自带邮件)
  20. 阿里云oss 收费标准细则,太鸡贼了,不要傻傻的以为只收你存储的钱

热门文章

  1. word文档中表格顶头怎么调整_word使用技巧之-Word文字处理技巧,学会不求人!...
  2. 第十三周作业-必做3
  3. python实现插值填充有序均匀点云空洞
  4. 工业相机和镜头选型技巧
  5. 哪个学校计算机考研945,2018年郑州大学945软件工程专业基础综合考研复习资料...
  6. 02读书笔记:《编码》-隐匿在计算机软硬件背后的语言(12-14章)
  7. 无插件使用Eclipse和Resin调试WEB应用(Debug Web App In Ecli...
  8. 爬虫出现selenium.common.exceptions.NoSuchWindowException: Message: Browsing context has been discarded
  9. 餐厅点菜c语言程序代码,餐馆点菜系统C语言源代码.pdf
  10. 【JAVA SE】三万字终极魔典 面向对象编程深度讲解(包+继承+多态+抽象类+接口 全面剖析)