Java锁的种类以及辨析(二):自旋锁的其他种类
作者:山鸡
锁作为并发共享数据,保证一致性的工具,在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锁的种类以及辨析(二):自旋锁的其他种类相关推荐
- 辨析:自旋锁与信号量
自旋锁(Spinlock) 信号量(Semaphore): 1. 自旋锁与信号量简介 自旋是锁的一种实现方式,通过忙等待("自旋,spinning")来实现[例如通过while循环 ...
- 自旋锁和互斥锁实例_多线程编程之自旋锁
一.什么是自旋锁 一直以为自旋锁也是用于多线程互斥的一种锁,原来不是! 自旋锁是专为防止多处理器并发(实现保护共享资源)而引入的一种锁机制.自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用 ...
- Linux 锁机制(3)之自旋锁
Linux 锁机制(3)之自旋锁 1. 自旋锁 1.1 两种锁 1.2 自旋锁 1.3 自旋名字来源:自旋锁一直循环等待,直到获取锁为止. 1.4 自旋锁优点: 2 自旋锁特点/使用: 2.1 临界区 ...
- 一文看懂临界区、互斥锁、同步锁、临界区、信号量、自旋锁等名词!
点击上方"业余草",选择"置顶公众号" 第一时间获取技术干货和业界资讯! 关于线程安全的专有名词有一大堆.你们突然之间问我这个名词是什么意思,那个名词是什么意思 ...
- 自旋锁与互斥锁的对比、手工实现自旋锁
自旋锁与互斥锁的对比.手工实现自旋锁 版权声明:本文为博主原创文章,转载请注明出处,谢谢. https://blog.csdn.net/FreeeLinux/article/details/53695 ...
- Juc07_乐观锁和悲观锁、公平锁和非公平锁、递归锁(可重入锁)、死锁及排查、自旋锁
文章目录 ①. 乐观锁和悲观锁 ②. 公平锁和非公平锁 ③. 可重入锁(又名递归锁) ④. 死锁及排查 ⑥. 自旋锁 ①. 乐观锁和悲观锁 ①. 悲观锁(synchronized关键字和Lock的实现 ...
- 锁优化:逃逸分析、自旋锁、锁消除、锁粗化、轻量级锁和偏向锁
1. 逃逸分析 Escape Analysis 1.1 逃逸分为两种: 方法逃逸:当一个对象在方法中被定义后,可能作为调用参数被外部方法说引用. 线程逃逸:通过复制给类变量或者作为实例变量在其他线程中 ...
- 轻量级锁的加锁和解锁逻辑-自旋锁
轻量级锁在加锁过程中,用到了自旋锁 所谓自旋,就是指当有另外一个线程来竞争锁时,这个线程会在原地循环等待,而不是把该线程给阻塞,直到那个获得锁的线程释放锁之后,这个线程就可以马上获得锁的. 注意,锁在 ...
- 【面试 分布式锁详细解析】续命 自旋锁 看门狗 重入锁,加锁 续命 解锁 核心源码,lua脚本解析,具体代码和lua脚本如何实现
Redisson实现分布式锁原理 自己实现锁续命 在 controller 里开一个 线程 (可以为 守护线程) 每10秒,判断一个 这个 UUID是否存在,如果 存在,重置为 30秒. 如果不存在, ...
- java锁的种类以及辨析(一):自旋锁
java锁的种类以及辨析(一):自旋锁 1.自旋锁 自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区.如下 public class SpinLock ...
最新文章
- SAP 预制发票报错 -Material 20000000 D119223073 in valuation area VNSM has inconsistant ML data- 之对策
- NR 5G EN-DC架构下的5G无线承载
- python语言是什么时候诞生的_python诞生于什么时候
- python下载后如何使用-如何使用Python通过HTTP下载文件?
- AutoHotkey 使用笔记
- 微信小程序 没有找到可以构建的npm包
- flutter自定义弹窗
- OpenGL ES GLKit初探
- BugkuCTF-MISC题where is flag3
- 编译mate-control-center:error: required directory ./help does not exist
- 实验一matlab编程基础,实验一、MATLAB编程基础及典型实例.doc
- UE4影视特效学习资源整理
- uni-app(vue小程序)学习笔记
- 计算机电源烧保险,ATX电脑电源保险换了就烧怎么维修?
- 计算机怎么设置默认桌面,盒子如何将沙发桌面设置成默认桌面?
- Python学习记录(一)
- 数据中心的端口密度该如何增加?
- 【Tensorflow】你真的懂TensorFlow吗?Tensor是神马?为什么还会Flow?
- Sublime Text3 Python配置
- 51单片机ALE引脚