Java 中的锁原理、锁优化、CAS、AQS 详解!

Java中的锁[原理、锁优化、CAS、AQS] 本文作者:景小财 作者简介:美团外卖活动业务负责人 1、为什么要用锁? 锁-是为了解决并发操作引起的脏读、数据不一致的问题。 2、锁实现的基本原理 2.1、volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方... 阅读详情

源码精品专栏

 

来源:jianshu.com/p/e674ee68fd3f

  • 1、为什么要用锁?

  • 2、锁实现的基本原理

    • 2.1、volatile

    • 2.2、synchronized

    • 2.3、CAS

  • 3、Java中的锁实现

    • 3.1、队列同步器(AQS)

  • 4、锁的使用用例

    • 4.1、ConcurrentHashMap的实现原理及使用


1、为什么要用锁?

锁-是为了解决并发操作引起的脏读、数据不一致的问题。

2、锁实现的基本原理

2.1、volatile

Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便。

volatile在多处理器开发中保证了共享变量的“ 可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。

结论:如果volatile变量修饰符使用恰当的话,它比synchronized的使用和执行成本更低,因为它不会引起线程上下文的切换和调度。

2.2、synchronized

synchronized通过锁机制实现同步。

先来看下利用synchronized实现同步的基础:Java中的每一个对象都可以作为锁。

具体表现为以下3种形式。

  • 对于普通同步方法,锁是当前实例对象。

  • 对于静态同步方法,锁是当前类的Class对象。

  • 对于同步方法块,锁是Synchonized括号里配置的对象。

当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。

2.2.1 synchronized实现原理

synchronized是基于Monitor来实现同步的。

Monitor从两个方面来支持线程之间的同步:

  • 互斥执行

  • 协作

1、Java 使用对象锁 ( 使用 synchronized 获得对象锁 ) 保证工作在共享的数据集上的线程互斥执行。

2、使用 notify/notifyAll/wait 方法来协同不同线程之间的工作。

3、Class和Object都关联了一个Monitor。

Monitor 的工作机理

  • 线程进入同步方法中。

  • 为了继续执行临界区代码,线程必须获取 Monitor 锁。如果获取锁成功,将成为该监视者对象的拥有者。任一时刻内,监视者对象只属于一个活动线程(The Owner)

  • 拥有监视者对象的线程可以调用 wait() 进入等待集合(Wait Set),同时释放监视锁,进入等待状态。

  • 其他线程调用 notify() / notifyAll() 接口唤醒等待集合中的线程,这些等待的线程需要重新获取监视锁后才能执行 wait() 之后的代码。

  • 同步方法执行完毕了,线程退出临界区,并释放监视锁。

参考文档:https://www.ibm.com/developerworks/cn/java/j-lo-synchronized

2.2.2 synchronized具体实现

1、同步代码块采用monitorenter、monitorexit指令显式的实现。

2、同步方法则使用ACC_SYNCHRONIZED标记符隐式的实现。

通过实例来看看具体实现:

public class SynchronizedTest {

    public synchronized void method1(){
        System.out.println("Hello World!");
    }

    public  void method2(){
        synchronized (this){
            System.out.println("Hello World!");
        }
    }
}

javap编译后的字节码如下:

monitorenter

每一个对象都有一个monitor,一个monitor只能被一个线程拥有。当一个线程执行到monitorenter指令时会尝试获取相应对象的monitor,获取规则如下:

  • 如果monitor的进入数为0,则该线程可以进入monitor,并将monitor进入数设置为1,该线程即为monitor的拥有者。

  • 如果当前线程已经拥有该monitor,只是重新进入,则进入monitor的进入数加1,所以synchronized关键字实现的锁是可重入的锁。

  • 如果monitor已被其他线程拥有,则当前线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor。

monitorexit

只有拥有相应对象的monitor的线程才能执行monitorexit指令。每执行一次该指令monitor进入数减1,当进入数为0时当前线程释放monitor,此时其他阻塞的线程将可以尝试获取该monitor。

2.2.3 锁存放的位置

锁标记存放在Java对象头的Mark Word中。

Java对象头长度

32位JVM Mark Word 结构

32位JVM Mark Word 状态变化

64位JVM Mark Word 结构

2.2.3 synchronized的锁优化

JavaSE1.6为了减少获得锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”。

在JavaSE1.6中,锁一共有4种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态,这几个状态会随着竞争情况逐渐升级。

锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。这种锁升级却不能降级的策略,目的是为了提高获得锁和释放锁的效率。

偏向锁:

无锁竞争的情况下为了减少锁竞争的资源开销,引入偏向锁。

轻量级锁:

轻量级锁所适应的场景是线程交替执行同步块的情况。

锁粗化(Lock Coarsening):也就是减少不必要的紧连在一起的unlock,lock操作,将多个连续的锁扩展成一个范围更大的锁。

锁消除(Lock Elimination):锁削除是指虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行削除。

适应性自旋(Adaptive Spinning):自适应意味着自旋的时间不再固定了,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也很有可能再次成功,进而它将允许自旋等待持续相对更长的时间,比如100个循环。另一方面,如果对于某个锁,自旋很少成功获得过,那在以后要获取这个锁时将可能省略掉自旋过程,以避免浪费处理器资源。

2.2.4 锁的优缺点对比

2.3、CAS

CAS,在Java并发应用中通常指CompareAndSwap或CompareAndSet,即比较并交换。

1、CAS是一个原子操作,它比较一个内存位置的值并且只有相等时修改这个内存位置的值为新的值,保证了新的值总是基于最新的信息计算的,如果有其他线程在这期间修改了这个值则CAS失败。CAS返回是否成功或者内存位置原来的值用于判断是否CAS成功。

2、JVM中的CAS操作是利用了处理器提供的CMPXCHG指令实现的。

优点:

  • 竞争不大的时候系统开销小。

缺点:

  • 循环时间长开销大。

  • ABA问题。

  • 只能保证一个共享变量的原子操作。

3、Java中的锁实现

3.1、队列同步器(AQS)

队列同步器AbstractQueuedSynchronizer(以下简称同步器),是用来构建锁或者其他同步组件的基础框架。

3.1.1、它使用了一个int成员变量表示同步状态。

3.1.2、通过内置的FIFO双向队列来完成获取锁线程的排队工作。

  • 同步器包含两个节点类型的应用,一个指向头节点,一个指向尾节点,未获取到锁的线程会创建节点线程安全(compareAndSetTail)的加入队列尾部。同步队列遵循FIFO,首节点是获取同步状态成功的节点。

  • 未获取到锁的线程将创建一个节点,设置到尾节点。如下图所示:

  • 首节点的线程在释放锁时,将会唤醒后继节点。而后继节点将会在获取锁成功时将自己设置为首节点。如下图所示:

3.1.3、独占式/共享式锁获取

独占式:有且只有一个线程能获取到锁,如:ReentrantLock。

共享式:可以多个线程同时获取到锁,如:CountDownLatch

独占式

  • 每个节点自旋观察自己的前一节点是不是Header节点,如果是,就去尝试获取锁。

  • 独占式锁获取流程:

共享式:

  • 共享式与独占式的区别:

  • 共享锁获取流程:

4、锁的使用用例

4.1、ConcurrentHashMap的实现原理及使用

ConcurrentHashMap类图

ConcurrentHashMap数据结构

结论:ConcurrentHashMap使用的锁分段技术。首先将数据分成一段一段地存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

 

Java~并发编程CAS和AQS原理刨析,东软java面试题 if (!} else { 阅读详情

相关推荐

Java外置锁实现原理

Java中的锁,如,ReentrantLock(显式锁)、CountDownLatch(闭锁)等都是基于AQS(队列同步器)来实现的,AQS又是CLH队列锁的一种变体实现。下面对这些锁的知识进行详细介绍。

ZH的博客 205

java cas 和AQS

什么是CAS机制 CAS是英文单词Compare And Swap的缩写,翻译过来就是比较并替换。 CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。 更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。 CAS是英文单词Compare And Swap的缩写,翻译过来就是比较并替换。 CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。 更新一个变量的时候,只有当变量的预期值A和内存地址

Meiko记录 1131

无线传感器网络非均匀分簇路由协议:MATLAB仿真实现与能量均衡设计

无线传感器网络(WSN)中,节点能量受限且难以补充,路由协议的设计直接决定网络生命周期。传统均匀分簇如LEACH易引发能量空洞,导致基站附近节点过早死亡。非均匀分簇通过动态调整簇头竞争半径,让近基站簇头承担更少簇内任务,保留能量用于数据转发,从而实现全网能耗均衡。本文从能耗模型、簇头选举、成簇机制到多跳路由,剖析基于MATLAB的完整仿真框架,并给出关键参数调优与常见问题排查方法。该实现适用于课程设计、毕业设计及学术对比实验,为研究WSN能量均衡策略提供了可直接运行的baseline。

weixin_34006965的博客 419

【Java并发编程】AQS和CAS

AQS和CAS

weixin_44735928的博客 1715

安装matlab_Matlab+yalmip+cplex安装教程及算例

数学建模/科研学习推荐学习软件:Matlab+yalmip+cplex安装教程及算例其实绝大多数本科生都是在用Matlab和LINGO求解优化问题,Matlab可以求解一般优化问题,但是当优化问题规模比较大或者在应对一些非线性问题时候,Matlab会出现求解时间长,求解效率低,甚至难以求解等问题。Matlab+yalmip+cplex是Matlab通过调用商业软件cplex求解,求解时间短,这里简...

weixin_28939637的博客 5005

AgentScope Java多智能体框架

AgentScope Java 的核心设计理念是“Agent-Oriented Programming” (面向智能体编程)。

zzz19920821的博客 1733

Java中的锁原理、锁优化、CAS、AQS详解!

点击上方"Java学习之道",选择"关注"公众号每天10:24,干货准时送达!本文来源:jianshu.com/p/e674ee68fd3f 一、为什么要用锁?锁-是为...

Java学习之道 2172

从波形到代码:手把手调试GaN图腾柱PFC的过零点切换与软启动策略

本文详细解析了GaN图腾柱无桥Boost PFC电路在过零点切换与软启动策略中的调试方法。通过波形分析、代码实现和寄存器配置,提供了解决误开通、震荡波形等问题的实用方案,帮助工程师优化电源设计效率与可靠性。

weixin_30831529的博客 421

java cas原理_Java中的锁原理、锁优化、CAS、AQS详解!

一、为什么要用锁?锁-是为了解决并发操作引起的脏读、数据不一致的问题。二、锁实现的基本原理2.1、volatileJava编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便。volatile在多处理器开发中保证了共享变量的“ 可见性”。可见性的意思是当一个线程修改一个共享变量时...

weixin_39703773的博客 74

一文读懂无人机AI识别算法,原理、技术、应用

本文详细介绍了无人机识别算法的工作原理、技术优势以及在多个行业的应用前景,展现了其在提升安全监控、资源管理和应急响应中的关键作用。尽管无人机识别算法在多个领域展现出巨大潜力,但仍面临技术挑战,如算法的准确性、数据的实时处理能力以及对复杂环境的适应性。4. 消防与城市管理: 无人机识别算法在消防和城市管理中的应用,为相关部门提供了及时的信息支持,提升了应急处置能力和城市管理水平。1. 公安监控: 无人机识别算法在公安领域的应用,可以实时识别犯罪嫌疑人和违法行为,有效提升城市治安管理的智能化水平。

foiadrone的博客 1846

BMS应用软件开发 — 7 从特斯拉到问界:主流BMS硬件架构深度解析

本文深度解析了从特斯拉Model 3到问界M5的主流BMS硬件架构,探讨了BMS在电动汽车中的核心价值与应用软件开发的关键技术。通过对比分析两家厂商的硬件设计哲学、芯片选型策略及成本控制方法,揭示了BMS硬件系统如何影响电池性能与整车安全。文章特别分享了电压采样精度、EMC设计等实战经验,为BMS开发提供宝贵参考。

weixin_42554408的博客 455

JAVA CAS原理深度分析锁优化、CAS、AQS一文扫清知识盲区!

JAVA CAS原理深度分析锁优化、CAS、AQS一文扫清知识盲区! Java并发 在Java并发中,我们最初接触的应该就是synchronized关键字了,但是synchronized属于重量级锁,很多时候会引起性能问题,volatile也是个不错的选择,但是volatile不能保证原子性,只能在某些场合下使用。 像synchronized这种独占锁属于悲观锁,它是在假设一定会发生冲突的,那么加锁恰好有用,除此之外,还有乐观锁,乐观锁的含义就是假设没有发生冲突,那么我正好可以进行某项操作,如果要是发生.

a3961401的博客 4172

Redhawk:什么是timing window?

STA timing file中timing window的作用和计算方式

m0_61544122的博客 1万+

Java中的锁原理、锁优化、CAS、AQS,看这篇就对了!

01 为什么要用锁? 锁-是为了解决并发操作引起的脏读、数据不一致的问题。 02锁实现的基本原理 2.1、volatileJava编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便。volatile在多处理器开发中保证了共享变量的“ 可见性”。可见性的意思是...

田维常 571

【CT/电镜 重建教程 1.1】层析成像的精确实空间迭代重建算法(RESIRE)

在此,我们报告了RESIRE算法的发展用于准确的断层重建。与实空间迭代算法相比,RESIRE使用傅里叶切片定理或Radon变换作为正向投影,使用线性变换作为反向投影,两者都具有高精度。与EST和GENFIRE相比,RESIRE是一种实空间迭代算法,可以在并行计算中实现快速运行时间。

2401_87064292的博客 1060

SQL面试题——最大连续登陆问题

最大连续登陆是我们计算比较常用的指标,我们可以将其当成一个经典的SQL模型,后面我们也会陆续总结出其他的模型,你还知道其他的比较经典的SQL 吗?欢迎分享,或者你还知道其他的关于计算连续的指标?最大连续登陆重要的是计算思想,最大连续才是关键,登陆只是一个场景,要学会举一反三。

9010

java 中的锁 aqs_Java中的锁原理、锁优化、CAS、AQS详解!

作者:高广超www.jianshu.com/p/e674ee68fd3f一、为什么要用锁?锁-是为了解决并发操作引起的脏读、数据不一致的问题。二、锁实现的基本原理2.1、volatileJava编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便。volatile在多处理器开发中...

weixin_35765731的博客 216

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

上一篇: 用 ArrayList 还是 LinkedList?
下一篇: Spring Boot 项目的 API 接口防刷
公众号-芋道源码
博客等级 码龄10年 1625粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值