Java所有的锁:从基础到进阶

Java所有的锁:从基础到进阶

作为Java开发者,“锁”是绕不开的核心知识点——不管是日常开发中的线程安全,还是面试时的高频追问(比如升级、CAS原理、锁的选型),掌握所有锁的特性和适用场景,才能真正吃透并发编程。

很多人对锁的认知,只停留在“和Lock”的表面,分不清公平锁与非公平锁、乐观锁与悲观锁,更不懂锁升级的逻辑,导致开发中选型失误、性能瓶颈,面试时被问得哑口无言。

今天这篇文章,一次性讲透Java中所有锁!按“认知→分类→原理→实战→避坑”的逻辑,从基础到进阶,覆盖所有高频锁类型java锁类型,结合代码示例和面试考点,看完直接拿捏锁的核心知识,再也不用零散查资料。

为什么需要锁?

在Java并发编程中,线程安全的核心诉求是解决“多线程并发访问共享资源”的冲突问题——比如多个线程同时修改同一个变量、操作同一个文件,会导致数据不一致、竞态条件等问题。

锁的本质,就是通过“限制共享资源的并发访问”,保证同一时刻只有符合条件的线程能操作资源,从而避免上述问题。简单说,锁就是并发编程的“线程安全守护神”。

随着Java并发体系的完善,锁的分类越来越丰富,不同类型的锁适用于不同的并发场景。我们按“高频度、高实用性”的维度,逐一拆解所有锁类型,拒绝模糊表述,全程干货无废话。

第一维度:按同步语义分类(核心!面试必问)

这是锁最核心的分类,核心区别在于“对并发冲突的预期”,直接决定了锁的底层实现逻辑与性能特性,也是日常开发中锁选型的核心依据。

1. 悲观锁:假设冲突一定会发生

核心语义:先加锁,再操作。悲观锁认为,多线程并发时java锁类型,数据修改冲突是必然的,所以在操作共享资源前,必须先获取锁,阻塞其他线程,直到当前线程操作完成并释放锁。

底层实现:依赖操作系统的互斥量(Mutex)或信号量,存在内核态与用户态的上下文切换开销,性能相对较低,但安全性极高。

典型实现:

代码示例(与):

适用场景:高冲突、写操作频繁的场景(如金融转账、库存扣减),安全性优先于性能。

2. 乐观锁:假设冲突不会发生

核心语义:先操作,后校验。乐观锁认为,多线程并发时,数据修改冲突的概率很低,所以无需提前加锁,直接操作共享资源,仅在提交操作时检查资源是否被修改。

底层实现:基于CAS( and Swap,比较并交换)原子操作或版本号机制,无阻塞、无上下文切换开销,性能优于悲观锁,但需要处理冲突重试逻辑。

典型实现:

代码示例(与版本号机制):

面试高频提醒:乐观锁并非“无锁”,而是“无阻塞锁”;悲观锁并非“低效锁”,而是“兜底锁”,二者无绝对优劣,核心是根据并发冲突频率选型。

适用场景:低冲突、读操作频繁的场景(如缓存更新、计数器),性能优先于安全性。

第二维度:按锁的排他性分类

核心区别在于“同一时刻,允许多少个线程获取锁”,直接决定了锁的并发能力,也是JUC包下锁的核心设计维度(基于AQS的两种核心模式)。

1. 独占锁(排他锁):同一时刻仅一个线程持有

核心语义:同一时刻,只有一个线程能获取锁,其他线程获取失败则进入等待队列,具有强排他性(类似“一人使用,其他人排队”),主要用于写操作。

底层依赖:基于AQS的独占模式(/钩子方法)。

典型实现:、、ck.(写锁)。

核心特点:安全性高,但并发能力弱,适合写操作场景(如修改数据、删除数据)。

2. 共享锁:同一时刻多个线程持有

核心语义:同一时刻,允许多个线程同时获取锁,无排他性(类似“多人同时阅读同一本书”),仅阻止写线程获取锁,主要用于读操作。

底层依赖:基于AQS的共享模式(/钩子方法)。

典型实现:ck.(读锁)、(信号量)、(倒计时器)。

核心特点:并发能力强,适合读多写少场景(如查询数据、统计数据)。

第三维度:按锁的公平性分类

核心区别在于“线程获取锁的顺序”,即是否遵循“先到先得(FIFO)”原则,影响锁的公平性与性能,面试中经常被问“是公平锁还是非公平锁”。

1. 公平锁:先到先得,拒绝插队

核心语义:线程获取锁的顺序,严格遵循“FIFO”原则,先请求锁的线程先获取锁,不允许“插队”,能避免线程饥饿(长期得不到锁)。

底层实现:线程获取锁时,先检查等待队列是否有前驱线程,若有则排队,无则尝试获取锁。

典型实现:(构造方法传入true)、ck(公平模式)。

核心特点:公平性高,但频繁切换线程会增加性能开销,吞吐量较低,适合对公平性要求高的场景(如金融交易)。

2. 非公平锁:允许插队,优先性能

核心语义:线程获取锁时Java所有的锁:从基础到进阶,不遵循FIFO原则,允许“插队”——刚释放锁的线程可再次立即获取锁,无需排队,减少线程切换开销。

底层实现:线程获取锁时,先尝试CAS获取锁,失败再加入等待队列,减少线程切换开销。

典型实现:(默认非公平)、(默认非公平,构造方法传入false)。

核心特点:公平性低,可能导致线程饥饿,但性能高、吞吐量高,适用于大多数并发场景(日常开发默认选择)。

第四维度:按锁的重入性分类

核心区别在于“持有锁的线程是否能再次获取该锁”java锁类型,避免线程自身死锁,是锁的基础特性,很多新手容易忽略这一点。

1. 可重入锁:持有锁的线程可再次获取

核心语义:持有锁的线程,可再次获取该锁(重入),锁内部会记录“重入次数”,释放时需释放对应次数,直到重入次数为0,锁才真正释放。

底层实现:通过记录“持有锁的线程ID”和“重入次数”,避免线程自身死锁。

典型实现:(可重入)、(可重入,名字就带)、ck。

核心优势:避免线程自身死锁,简化嵌套同步逻辑(如方法A调用方法B,二者均加锁,可重入锁不会导致死锁)。

代码示例(可重入锁嵌套):

2. 不可重入锁:持有锁的线程无法再次获取

核心语义:持有锁的线程,无法再次获取该锁,若尝试获取,会导致自身死锁。

典型实现:JUC包下无直接实现,自定义锁可实现不可重入语义(如简单的CAS锁)、Linux下的(默认不可重入)。

核心劣势:易导致线程自身死锁,适用场景极少,仅用于特殊同步需求(日常开发几乎不用)。

第五维度:按底层实现分类(JVM锁升级重点)

核心区别在于“锁的实现层面”,直接决定锁的性能开销,尤其是的锁升级机制,是面试高频难点(JDK1.6后重大优化)。

核心前提:锁升级是不可逆的!一旦从偏向锁升级到轻量级锁,就不能再回退;一旦升级到重量级锁,就只能一直保持重量级锁状态。

1. 偏向锁:无竞争场景的最优解

核心场景:当只有一个线程反复获取、释放同一把锁,没有任何其他线程参与竞争时(如单线程执行同步代码块),JVM会自动使用偏向锁。

核心原理:“偏心”绑定线程——JVM在对象头(Mark Word)中记录当前持有锁的线程ID,后续该线程再获取锁时,无需做任何同步操作(不用CAS、不用切换内核态),直接进入同步代码块,开销几乎可以忽略不计。

优势与不足:开销极小,适合无竞争场景;但一旦有其他线程参与竞争,需撤销偏向锁,触发升级,撤销过程有一定开销。

2. 轻量级锁:轻度竞争场景的过渡方案

核心场景:有少量线程交替获取锁(没有同时争抢,即“自旋竞争”),此时偏向锁被撤销,升级为轻量级锁。

核心原理:线程进入同步代码块前,会在自己的栈帧中创建“锁记录”(Lock ),记录锁对象的Mark Word副本;通过CAS操作,将锁对象的Mark Word更新为自己的锁记录地址,CAS成功则获取锁,失败则进入自旋(不断尝试CAS)。

优势与不足:无需切换内核态,开销远小于重量级锁;但自旋会消耗CPU资源,若锁持有时间过长,自旋会变成无效消耗,触发升级为重量级锁。

3. 重量级锁:重度竞争场景的终极保障

核心场景:有大量线程同时争抢同一把锁(重度竞争),或锁被持有时间很长,自旋无法高效获取锁时,轻量级锁升级为重量级锁。

核心原理:依赖操作系统的互斥量(Mutex Lock),属于内核态锁。线程获取锁失败时,不再自旋,而是直接放弃CPU执行权,进入操作系统的阻塞队列,直到持有锁的线程释放锁,操作系统才会唤醒队列中的线程。

优势与不足:稳定性高,能应对重度竞争;但开销最大,每次获取、释放锁都需要切换用户态和内核态,线程阻塞/唤醒开销大。

锁升级完整流程(必背)

无锁 → 偏向锁(无竞争) → 轻量级锁(轻度竞争Java所有的锁:从基础到进阶,CAS+自旋) → 重量级锁(重度竞争,阻塞等待),一旦升级,无法回退。

第六维度:其他高频锁类型(面试拓展)1. 自旋锁:轻量级锁的核心实现

核心语义:线程获取锁失败时,不立即阻塞,而是循环尝试获取锁(自旋),直到获取成功或达到自旋阈值。

底层实现:基于CAS操作,无上下文切换开销,适合锁持有时间短、竞争不激烈的场景;自旋次数达到阈值(JVM默认10次),则升级为重量级锁。

注意:JDK1.6后引入“自适应自旋锁”,自旋次数会根据之前的竞争情况动态调整,无需手动配置。

2. 分段锁:的核心优化

核心语义:将锁的粒度细化,把一个大的容器(如)分成多个段(),每个段对应一把锁,多线程访问不同段时,无需竞争同一把锁,提高并发性能。

典型实现:JDK1.7的(JDK1.8后改为CAS+ ,取消分段锁,但分段锁的思想仍需掌握)。

3. 无锁:乐观锁的极致形态

核心语义:完全不依赖锁机制,直接通过CPU原子指令(如CAS)或线程本地存储()保证线程安全,不存在锁竞争,性能最优。

典型实现:系列原子类、.CAS、(线程隔离,无共享则无竞争)。

注意:无锁并非“不需要保证安全”,而是通过非锁机制实现安全,适用于线程间无共享数据修改或修改冲突极少的场景。

实战总结:锁的选型指南(开发/面试都能用)

掌握了所有锁的特性后,核心是“按需选型”,避免盲目使用重量级锁,也避免滥用乐观锁导致冲突问题。整理了一张选型表,直接套用:

面试高频避坑点(必记)

公告:
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299

资源库 - 资源分享下载网 » Java所有的锁:从基础到进阶

常见问题FAQ

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们