作者:山鸡

锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类型却很少被提及。本系列文章将分析JAVA下常见的锁名称以及特性,为大家答疑解惑。

2.自旋锁的其他种类

上篇我们讲到了自旋锁,在自旋锁中 另有三种常见的锁形式:TicketLock ,CLHlock 和MCSlock

Ticket锁主要解决的是访问顺序的问题,主要的问题是在多核cpu上

package com.alipay.titan.dcc.dal.entity;import java.util.concurrent.atomic.AtomicInteger;public class TicketLock {private AtomicInteger                     serviceNum = new AtomicInteger();private AtomicInteger                     ticketNum  = new AtomicInteger();private static final ThreadLocal<Integer> LOCAL      = new ThreadLocal<Integer>();public void lock() {int myticket = ticketNum.getAndIncrement();LOCAL.set(myticket);while (myticket != serviceNum.get()) {}}public void unlock() {int myticket = LOCAL.get();serviceNum.compareAndSet(myticket, myticket + 1);}
}

每次都要查询一个serviceNum 服务号,影响性能(必须要到主内存读取,并阻止其他cpu修改)。

CLHLock 和MCSLock 则是两种类型相似的公平锁,采用链表的形式进行排序,

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;public class CLHLock {public static class CLHNode {private volatile boolean isLocked = true;}@SuppressWarnings("unused")private volatile CLHNode                                           tail;private static final ThreadLocal<CLHNode>                          LOCAL   = new ThreadLocal<CLHNode>();private static final AtomicReferenceFieldUpdater<CLHLock, CLHNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(CLHLock.class,CLHNode.class, "tail");public void lock() {CLHNode node = new CLHNode();LOCAL.set(node);CLHNode preNode = UPDATER.getAndSet(this, node);if (preNode != null) {while (preNode.isLocked) {}preNode = null;LOCAL.set(node);}}public void unlock() {CLHNode node = LOCAL.get();if (!UPDATER.compareAndSet(this, node, null)) {node.isLocked = false;}node = null;}
}

CLHlock是不停的查询前驱变量, 导致不适合在NUMA 架构下使用(在这种结构下,每个线程分布在不同的物理内存区域)

MCSLock则是对本地变量的节点进行循环。不存在CLHlock 的问题。

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;public class MCSLock {public static class MCSNode {volatile MCSNode next;volatile boolean isLocked = true;}private static final ThreadLocal<MCSNode>                          NODE    = new ThreadLocal<MCSNode>();@SuppressWarnings("unused")private volatile MCSNode                                           queue;private static final AtomicReferenceFieldUpdater<MCSLock, MCSNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(MCSLock.class,MCSNode.class, "queue");public void lock() {MCSNode currentNode = new MCSNode();NODE.set(currentNode);MCSNode preNode = UPDATER.getAndSet(this, currentNode);if (preNode != null) {preNode.next = currentNode;while (currentNode.isLocked) {}}}public void unlock() {MCSNode currentNode = NODE.get();if (currentNode.next == null) {if (UPDATER.compareAndSet(this, currentNode, null)) {} else {while (currentNode.next == null) {}}} else {currentNode.next.isLocked = false;currentNode.next = null;}}
}

从代码上 看,CLH 要比 MCS 更简单,

CLH 的队列是隐式的队列,没有真实的后继结点属性。

MCS 的队列是显式的队列,有真实的后继结点属性。

JUC ReentrantLock 默认内部使用的锁 即是 CLH锁(有很多改进的地方,将自旋锁换成了阻塞锁等等)。

Java锁的种类以及辨析(二):自旋锁的其他种类相关推荐

  1. 辨析:自旋锁与信号量

    自旋锁(Spinlock) 信号量(Semaphore): 1. 自旋锁与信号量简介 自旋是锁的一种实现方式,通过忙等待("自旋,spinning")来实现[例如通过while循环 ...

  2. 自旋锁和互斥锁实例_多线程编程之自旋锁

    一.什么是自旋锁 一直以为自旋锁也是用于多线程互斥的一种锁,原来不是! 自旋锁是专为防止多处理器并发(实现保护共享资源)而引入的一种锁机制.自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用 ...

  3. Linux 锁机制(3)之自旋锁

    Linux 锁机制(3)之自旋锁 1. 自旋锁 1.1 两种锁 1.2 自旋锁 1.3 自旋名字来源:自旋锁一直循环等待,直到获取锁为止. 1.4 自旋锁优点: 2 自旋锁特点/使用: 2.1 临界区 ...

  4. 一文看懂临界区、互斥锁、同步锁、临界区、信号量、自旋锁等名词!

    点击上方"业余草",选择"置顶公众号" 第一时间获取技术干货和业界资讯! 关于线程安全的专有名词有一大堆.你们突然之间问我这个名词是什么意思,那个名词是什么意思 ...

  5. 自旋锁与互斥锁的对比、手工实现自旋锁

    自旋锁与互斥锁的对比.手工实现自旋锁 版权声明:本文为博主原创文章,转载请注明出处,谢谢. https://blog.csdn.net/FreeeLinux/article/details/53695 ...

  6. Juc07_乐观锁和悲观锁、公平锁和非公平锁、递归锁(可重入锁)、死锁及排查、自旋锁

    文章目录 ①. 乐观锁和悲观锁 ②. 公平锁和非公平锁 ③. 可重入锁(又名递归锁) ④. 死锁及排查 ⑥. 自旋锁 ①. 乐观锁和悲观锁 ①. 悲观锁(synchronized关键字和Lock的实现 ...

  7. 锁优化:逃逸分析、自旋锁、锁消除、锁粗化、轻量级锁和偏向锁

    1. 逃逸分析 Escape Analysis 1.1 逃逸分为两种: 方法逃逸:当一个对象在方法中被定义后,可能作为调用参数被外部方法说引用. 线程逃逸:通过复制给类变量或者作为实例变量在其他线程中 ...

  8. 轻量级锁的加锁和解锁逻辑-自旋锁

    轻量级锁在加锁过程中,用到了自旋锁 所谓自旋,就是指当有另外一个线程来竞争锁时,这个线程会在原地循环等待,而不是把该线程给阻塞,直到那个获得锁的线程释放锁之后,这个线程就可以马上获得锁的. 注意,锁在 ...

  9. 【面试 分布式锁详细解析】续命 自旋锁 看门狗 重入锁,加锁 续命 解锁 核心源码,lua脚本解析,具体代码和lua脚本如何实现

    Redisson实现分布式锁原理 自己实现锁续命 在 controller 里开一个 线程 (可以为 守护线程) 每10秒,判断一个 这个 UUID是否存在,如果 存在,重置为 30秒. 如果不存在, ...

  10. java锁的种类以及辨析(一):自旋锁

    java锁的种类以及辨析(一):自旋锁 1.自旋锁 自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区.如下 public class SpinLock ...

最新文章

  1. SAP 预制发票报错 -Material 20000000 D119223073 in valuation area VNSM has inconsistant ML data- 之对策
  2. NR 5G EN-DC架构下的5G无线承载
  3. python语言是什么时候诞生的_python诞生于什么时候
  4. python下载后如何使用-如何使用Python通过HTTP下载文件?
  5. AutoHotkey 使用笔记
  6. 微信小程序 没有找到可以构建的npm包
  7. flutter自定义弹窗
  8. OpenGL ES GLKit初探
  9. BugkuCTF-MISC题where is flag3
  10. 编译mate-control-center:error: required directory ./help does not exist
  11. 实验一matlab编程基础,实验一、MATLAB编程基础及典型实例.doc
  12. UE4影视特效学习资源整理
  13. uni-app(vue小程序)学习笔记
  14. 计算机电源烧保险,ATX电脑电源保险换了就烧怎么维修?
  15. 计算机怎么设置默认桌面,盒子如何将沙发桌面设置成默认桌面?
  16. Python学习记录(一)
  17. 数据中心的端口密度该如何增加?
  18. 【Tensorflow】你真的懂TensorFlow吗?Tensor是神马?为什么还会Flow?
  19. Sublime Text3 Python配置
  20. 51单片机ALE引脚

热门文章

  1. 图解ElasticSearch 搜索原理
  2. 还分不清 Cookie、Session、Token、JWT?
  3. Centos7搭建k8s环境教程,一次性成功,收藏了!
  4. 因用了Insert into select语句,美女同事被开除了!
  5. HashMap 为什么线程不安全?
  6. 深度学习框架盘点和实践!
  7. 保姆级NLP学习路线来啦!
  8. 全了!从Python入门到入魔
  9. 知乎热议:周志华弟子 旷视南京负责人跳槽高校
  10. Attention跟一维卷积有什么区别?