Java并发编程 - 锁 - 原理详解

Java并发编程核心详解:线程、锁、JMM与线程池实战 在Java后端开发中,并发编程是绕不开的核心技能,也是面试与线上问题排查的高频考点。它主要解决多线程环境下的原子性、可见性与有序性三大问题,具体实现依赖线程、锁、内存模型等基础机制。synchronized与volatile分别从互斥与内存屏障角度保证线程安全,而JMM(Java内存模型)与happens-before原则则定义了变量在并发访问时的可见性规则。进一步地,JUC中的锁、CAS、并发容器以及线程池,为复杂业务场景提供了高效且可控的并发工具。理解线程池的参数配置与拒绝策略,能够有效规避资源耗尽风险 阅读详情

Java并发编程中, 锁机制对控制线程间共享内存的使用有重要的意义. 那么在Java内部锁是如何实现的呢?

首先要明确一个概念.

Java中的锁是对象级别的概念, 也就是每个对象都天生可以作为一个锁使用.

究其底层实现, 实际上锁是存在于Java对象头的MarkWord字段里的, 根据锁的级别, 存储结构不同, 但是都存在一个2bit的锁标识位.


悲观锁

悲观锁是synchronize内部的实现机制, java 1.6之后, 对悲观锁进行了改进, 也就是现在不是所有同步操作都一定会被阻塞. 如今的悲观锁按照锁的获取与释放方式被划分为偏向锁, 轻量级锁, 重量级锁. 锁标识位分别为01, 00, 10. 这几种状态会随着锁的竞争情况逐渐升级(但是不会降级)

偏向锁

偏向锁是一种出现竞争才释放锁的机制.

具体来说, 作为锁的对象头部会保存一个偏向锁标识, 存储当前获得锁的线程ID. 假设当前是线程A获得了锁, 但是线程A执行完同步块之后并不释放锁, 而是等到其他线程竞争之后才进行锁的释放. 为什么要这样设计呢? 因为如果下次还是线程A来访问同一同步块, 那么就无需通过CAS操作来重新对锁对象的对象头进行更新, 简单比对一下线程id是否相等即可.

以下是偏向锁的获取与释放流程图:

偏向锁获取与释放

对上图的一点补充解释:

在竞争偏向锁的时候, 需要对持有偏向锁的线程进行检查, 如果线程已死, 则自动解锁, 将锁对象的对象头的markword中的线程id置空, 如果线程当前已不使用同步块, 解锁, 将锁对象的markword中额线程id置空, 并恢复线程. 同时其他线程可以通过CAS操作将锁对象的对象头markword中的对象id设置为自己的id, 也就是获得了偏向锁.

轻量级锁

当偏向锁的撤销与获取经常出现的时候(也就是锁的竞争经常发生的时候), 就会升级为轻量级锁.

线程通过CAS获取轻量级锁的方法与获取偏向锁的过程不同, 它总是将锁对象的Markword先拷贝到栈空间, 然后试图通过CAS更新Markword, 如果成功说明获得了锁, 如果失败说明其他线程成功更新了Markword(也就是获得了锁), 则通过自旋CAS尝试重新获取锁(始终消耗CPU时间片), 如果在较短的时间内成功, 则锁不会升级, 如果长时间未获得锁, 则锁会升级到重量级锁.

重量级锁

重量级锁在线程获得锁失败时不会进行自旋CAS尝试重新获取锁, 而是会进入阻塞态(让出CPU时间片, 在其他线程释放锁后由CPU调度重新进行锁竞争).

小结

三种锁并没有好坏之分, 分别有各自适用的场合:

锁优点缺点适用场景
偏向锁在没有锁竞争的情况下, 加锁极快, 且无需解锁如果较多线程竞争锁, 会使得加解锁的过程额外费时长时间一个线程访问同步块的场景
轻量级锁竞争线程不会阻塞, 响应快如果长时间无法获得锁, 自旋CAS会带来较大的CPU开销追求响应时间, 且同步块执行速度块的场景
重量级锁线程无法获取锁时总是阻塞, 及时让出CPU资源线程阻塞, 需要通过调度重新竞争锁, 响应缓慢追求高吞吐量, 且同步块执行时间较长的场景, 如包含大量I/O操作

乐观锁

乐观锁允许所有的线程在不发生阻塞的情况下创建一份共享内存的拷贝. 这些线程接下来可能会对它们的拷贝进行修改,并企图把它们修改后的版本通过CAS操作写回到共享内存. 如果, 另一个线程已经修改了共享内存, 这个线程将不得不再次获得一个新的拷贝, 在新的拷贝上做出修改, 并尝试再次通过CAS把它们写回到共享内存中去.

称之为"乐观锁"的原因就是, 线程获得它们想修改的数据的拷贝并做出修改, 乐观的假设在此期间没有其他线程对共享内存做出修改, 当这个乐观假设成立时, 这个线程仅仅在无锁的情况下完成共享内存的更新. 当这个假设不成立时, 线程所做的工作就会被丢弃.

无论乐观假设成功或者失败, 乐观锁总是没有使用锁进行并发的控制.

适用场景

乐观锁仅适用于共享内存竞用不是非常高的情况.

如果共享内存上的需要修改的内容非常多, 那么会因为CAS更新共享内存失败, 从而浪费大量的CPU周期用在重新拷贝和修改上.

典型用例

AtomicInteger等.

到底是什么决定了二极管的最高工作频率? 硬件工程师,应该都用过二极管的吧,不过也许有一个误区,大多数人可能并不知道,或者说是理解有问题,下面就来细细说下。 一个问题 先提一个问题:到底是什么决定了二极管的最高工作频率? 估计有不少人会回答是二极管反向恢复时间Trr,也有人会说是二极管结电容,那到底谁是对的呢?或者说都一样,反向恢复时间由结电容决定? 到底什么决定了二极管的最高工作频率,我们暂且不论,不过需要知道的是,二极管的反向恢复时间和结电容根本就是两回事,反向恢复时间绝不能等同于结电容的充放电时间。 为什么我这么说呢?. 阅读详情

相关推荐

深入分析RAG知识库多模态数据预处理

多模态企业数据预处理是构建高质量RAG知识库的关键环节。本文详解了处理流程:1)文档格式识别与路由;2)多模态内容提取(文本、图像、音视频);3)结构解析与语义重建;4)数据清洗与增强;5)智能分块(强调语义完整性);6)元数据注入。推荐使用开源工具如PaddleOCR、Whisper、BLIP-2等,或商业API处理复杂场景,最终生成带丰富元数据的结构化内容,为后续向量化检索奠定基础。

qq_35354529的博客 1378

Java 中的各种锁及其原理

概览 在并发编程中,锁是一种常用的保证线程安全的方法。Java 中常用的锁主要有两类,一种是 Synchronized 修饰的锁,被称为 Java 内置锁或监视器锁。另一种就是在 J2SE 1.5 版本之后的 java.util.concurrent 包(下称 j.u.c 包)中的各类同步器,包括 ReentrantLock(可重入锁),ReentrantReadWriteLock(可重入读写锁),Semaphore(信号量),CountDownLatch 等。这些同步器都是基于 AbstractQueue

Panda的学习日常 2317

SpringBoot+Vue实现图片上传

SpringBoot+Vue实现图片上传

叶♥璃 2730

java锁机制详解

java锁机制 1. 乐观锁 VS 悲观锁 ​ 悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁。 ​ 乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重

weixin_47071411的博客 6851

AI 自动生成商业计划书:AIGC 如何助力创业者?

在创业的早期阶段,商业计划书(Business Plan)是至关重要的。它不仅用于吸引投资者、明确发展路径,还能帮助团队对业务模式、市场定位和财务预测有清晰认知。然而,撰写一份高质量的商业计划书往往需要投入大量时间和精力。如今,AIGC(AI Generated Content,人工智能生成内容)技术正在改变这一现状。借助 AIGC,创业者可以更快速、高效地创建商业计划书,并通过 AI 进行优化和数据分析。

2401_82808034的博客 3779

无符号整数、带符号整数溢出问题

让我们详细讲解一下带符号整数溢出和无符号整数溢出问题中,符号标志位 (SF)、零标志位 (ZF) 和进位标志位 (CF) 的行为方式

weixin_49342084的博客 2084

深入解析Java中锁机制以及底层原理

深入分析了Java各种锁的机制和原理

码星人 4414

基于NXP i.MX RT1180的无传感器FOC电机驱动实战指南

磁场定向控制(FOC)是一种先进的电机控制技术,它通过精密的数学变换,将三相交流电机的控制解耦为独立的转矩和磁场分量,从而实现高效、平稳、低噪音的驱动。其核心原理在于利用Park/Clark变换,在旋转坐标系下对电流进行线性控制。这项技术的价值在于显著提升了永磁同步电机(PMSM)的效率与动态性能,广泛应用于机器人、无人机和工业自动化等高精度场景。本文聚焦于利用NXP i.MX RT1180跨界处理器及其MCUXpresso SDK,快速实现一套完整的无传感器FOC解决方案。通过解析硬件平台选型、软件架构,

weixin_33925615的博客 302

Java锁机制详解

Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自JDK 8)、使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。Java中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。

m0_51431003的博客 1420

【STM32】STM32 CANFD外设的几种消息接收过滤模式

在控制器区域网络(CAN)系统中,正确配置消息过滤器对于有效管理网络通信至关重要。特别是在使用Flexible Data-rate Controller Area Network(FDCAN)时,选择合适的过滤器类型可以大大提高网络效率和消息处理速度。

林愿留的博客 6225

OpenClaw 2026 路线图详解:3 大协作能力升级与社区贡献增长 62% 的实证分析

介绍 OpenClaw 2026 如何通过上下文锚定(Context Anchoring)、协作质量定义和责任边界机制,将 AI 编程工具从单点补全升级为嵌入代码生命周期的协作对齐系统,并详解 `.openclaw/config.yaml` 中 `context_anchor` 配置的实操方法与效果

weixin_42545292的博客 382

【Java】锁的原理以及应用最详细教程

一、锁锁是一种互斥的机制,在多线程环境中实现对资源的协调与控制,凡是有资源被多线程共享,涉及到修改的情况就要考虑锁的加持。(0)Java锁原理0)引申:Java对象结构Java对象结构分为3部分:①对象头(包括:Mark Word(存储了当前对象运行时的状态信息,如HashCode、指向锁记录的指针等)、Class Pointer(指针,指向当前对象类型所在方法区中的Class信息));如图,MarkWord结构(jdk1.8)HotSpot 64位操作系统(一个对象的markWord在内存占用8字节)锁标

程序源日志的博客 2145

微信小程序 - {errCode: 10008, errno: 1500104, errMsg: “writeBLECharacteristicValue:fail write characteris

微信小程序errCode: 10008, errno: 1500104, errMsg: "writeBLECharacteristicValue:fail write characteristics error. 10008, errMsg=The value's length is invalid.",uni-app微信小程序报错,uniApp小程序调用蓝牙api报错,向低功耗蓝牙设备的某个特征写入数据时错误,UniApp微信小程序蓝牙API调用报错10008解决方案,蓝牙设备进行通信时,向设备写入数据

🏆 前端领域优质创作者 4429

java并发排它锁_Java并发编程—Java中的锁原理、锁优化、CAS、AQS详解

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

weixin_31477251的博客 110

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

java 变量锁_Java并发编程—Java中的锁原理、锁优化、CAS、AQS详解

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

weixin_39733812的博客 72

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Java并发编程(五):synchronized原理详解及锁优化

文章目录1 引言2 synchronized实现原理2.1 监视器锁(monitor)机制2.2 获取锁和释放锁的内存语义3 synchronized的锁优化3.1 JVM中对象的内存区域3.2 偏向锁3.3 轻量级锁3.4 各种锁的比较3.5 小结点点关注,不会迷路 1 引言 线程运行时拥有自己私有的栈空间,会在自己的栈空间运行,如果多线程间没有共享的数据也就是说多线程间并没有协作完成一件事情,那么,多线程就不能发挥优势,不能带来巨大的价值。那么共享数据的线程安全问题怎样处理?很自然而然的想法就是每一个线

少侠露飞的学习笔记 755

VC中sqlite的使用

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

Java 并发编程-不懂原理多吃亏(送书福利)

作者 | 加多 关注阿里巴巴云原生公众号,后台回复关键字“并发”,即可参与送书抽奖!** 导读:并发编程与 Java 中其他知识点相比较而言学习门槛较高,从而导致很多人望而却步。但无论是职场面试,还是高并发/高流量系统的实现,都离不开并发编程,于是能够真正掌握并发编程的人成为了市场迫切需求的人才。本文中,作者加多以通俗易懂的方式讲解了多线程并发编程从入门到实践需要掌握的理论知识与实...

weixin_30362801的博客 171

Java并发编程:全面解析锁策略、CAS与synchronized优化机制

本文解析Java并发核心机制:①六大锁策略(乐观/悲观锁、轻量/重量级锁、自旋/挂起锁、公平/非公平锁、可重入锁、读写锁)适用场景;②synchronized锁升级过程(偏向→轻量→重量级锁);③编译器优化(锁消除/粗化);④CAS原理、原子类实现、自旋锁及ABA问题解决方案(版本号)。开发者需根据场景选择策略,平衡安全与性能。

ZNing_1的博客 806

Java并发编程

一、并发编程的挑战 并发编程的目的是为了让程序运行的更快。 但并发编程也会带来很多问题:例如上下文切换、死锁、硬件软件资源限制等。 上下文切换 1、什么是上下文切换? cpu通过不断切换线程,让我们感觉多个线程同时执行。 这种切换前会保存上一个任务的状态,以便切换回此任务时,能加载这个任务的状态。 任务从保存到再加载就是一次上下文切换。 2、那么多线程一定快吗(并行一定比串行快吗?) 不一定,由于...

Rhin0cer0s的博客 326

吃透 synchronized 底层原理:从偏向锁到重量级锁的完整拆解

在 Java 并发编程中,是最基础也最常用的同步手段,但它的底层原理(尤其是锁升级、轻量级锁的 CAS 竞争逻辑)往往让初学者困惑。本文结合我在学习过程中与AI的对话,完整梳理的底层逻辑,重点突破轻量级锁的核心难点,希望能够帮助到大家。可重入性:同一线程可多次获取同一把锁(通过 Monitor 的 Recursion Count 实现),避免自己阻塞自己;非公平性:锁释放后,等待队列中的线程不保证按顺序获锁(新线程可能直接抢占,提升吞吐量);渐进式优化。

zzyllc的博客 899

Java 锁

1、多线程间的原子性、可见性、有序性是什么意思? 原子性:执行一个或者多个操作的时候,要么全部执行,要么都不执行,并且中间过程中不会被打断。独占锁 和 CAS 能够保证原子性。 可见性:指多线程访问同一个变量的时候,一个线程修改了变量的值,其他线程能够立刻看得到修改的值。锁 和 volatile 能够保证可见性。 有序性:程序执行的顺序按照代码先后的顺序执行。锁 和 volatile 能够保证有序性。 2、happens-before 原则有哪些? Java 内存模型具有一些先天的有序性,它通常叫做

u011035026的博客 301

java并发编程:管程、内存模型、无锁并发、线程池、AQS原理与锁、线程安全集合类、并发设计模式

java并发编程:管程、内存模型、无锁并发、线程池、AQS原理与锁、线程安全集合类、并发设计模式

Henrik-Yao的博客 1571

java并发编程应用(一)

整理自《java并发编程的艺术》 一,线程 进程:操作系统分配资源的最小单元,一个进程包含多条进程。 进程:操作系统调度的最小单元,也叫轻量级进程。一个进程可以创建多个线程,各个线程拥有各自的计数器,堆栈和局部变量等属性,并且能够访问共享的内存变量。 线程优先级:setPriority(int);优先级1-10; 线程状态: Daemon线程:是一种支持型线程,因为它主要被用作程序中后台调度...

zjltju1203的博客 615

Java 并发编程

Java并发编程系列: > Java 并发编程:核心理论 > Java并发编程:Synchronized及其实现原理 > Java并发编程:Synchronized底层优化(轻量级锁、偏向锁) > Java 并发编程:线程间的协作(wait/notify/sleep/yield/join) > Java 并发编程:volatile的使用及其原理 ...

weixin_43678962的博客 107

Java并发编程(总目录)

一.Java内存模型Java内存模型的抽象结构Java内存模型之happens-before二.Java并发编程基础Java多线程的概念和原理Java多线程的创建和启动线程的生命周期详解Thread类相关的API介绍如何安全的终止线程三.Java中的锁Java中各种锁的详解Java中的锁之Lock接口Java中的锁之重入锁:ReentrantLock四.Java并发容器和框架为什么要使用Concu...

yingjian2215的博客 122

并发编程之锁

一、原子性 问题 在下面的案例中,演示了两个线程分别去去调用 demo.incr 方法来对 i 这个变量进行叠加,预期结果应该是20000,但是实际结果却是小于等于20000的值。 public class AtomicDemo { int i=0; public void incr(){ i++; } public static void main(String[] args) throws InterruptedException {

紫乾2014的博客 165
上一篇: Java并发编程 - 常用容器(ConcurrentHashMap, ConcurrentLinkedQueue)
下一篇: Java并发编程 - 基础
congyh
博客等级 码龄15年 43粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值