news 2026/6/10 14:42:17

Java 锁机制全面解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 锁机制全面解析

今天我们来聊聊Java中的锁机制

一、为什么需要锁

在单线程程序中,所有代码按顺序执行,不会出现资源竞争的问题;但在多线程并发场景下,多个线程同时访问共享资源(如全局变量、数据库连接、文件等)时,会出现竞态条件,导致数据不一致。锁是解决多线程并发访问共享资源的工具,本质是给共享资源加独占权限,保证多线程对共享资源的互斥访问,解决线程安全问题。

二、Java中常见的锁实现

Synchronized

这是 Java 提供的原生关键字。它像是一个全自动洗衣机,你只需要把衣服丢进去(加上关键字),剩下的 JVM 帮你搞定。

特点:

  • 隐式锁:自动加锁/解锁,无需手动释放,即使抛异常也会释放;
  • 可重入、非公平锁;
  • JDK 1.6 后支持锁升级(偏向→轻量→重量);
  • 独占锁(悲观锁)。
public class SynchronizedUsage { // 1. 修饰实例方法:锁是当前对象(this) public synchronized void instanceMethod() {} // 2. 修饰静态方法:锁是当前类的Class对象 public static synchronized void staticMethod() {} // 3. 修饰代码块:锁是指定的对象(灵活) public void codeBlock() { // 锁对象可以是this、Class对象、自定义对象 synchronized (SynchronizedUsage.class) { // 临界区代码 } } }

ReentrantLock

它是java.util.concurrent.locks包下的一个类。它像是一个手动档汽车,更灵活,但也更考验车技。

特点:

  • 显式锁:需手动 lock()、unlock();
  • 可重入、可指定公平 / 非公平(默认非公平);
  • 支持可中断锁、超时获取锁;
  • 支持条件变量,可实现精准唤醒线程;
  • 独占锁(悲观锁)。
Lock lock = new ReentrantLock(); lock.lock(); // 手动加锁 try { // 临界区代码 } finally { lock.unlock(); // 必须在 finally 里手动释放,否则会造成死锁 }

三、锁的分类

Java 中的锁可以从多个维度分类,这些分类并非互斥,而是从不同视角描述锁的特性。

1. 按获取锁的顺序:公平锁 vs 非公平锁

  • 公平锁:多个线程按照申请锁的顺序来获取锁,缺点是频繁的队列切换会带来性能损耗;
  • 非公平锁:线程获取锁时尝试直接抢占,抢锁失败再进入等待队列,性能较高,缺点是可能导致部分线程长期等待。但性能收益远大于弊端。

2. 按对待并发的态度:乐观锁 vs 悲观锁

这是一种设计思想,并非具体的锁实现。

  • 悲观锁:总是假设最坏的情况,认为共享资源访问每次都会有冲突发生,所以先加锁再访问资源。适用写操作多、冲突率高的情况。
  • 乐观锁:认为冲突很少发生,先访问资源,只是在提交时检查是否有冲突。适用读操作多、冲突率低的情况。

3. 按资源访问方式:独享锁 vs 共享锁

  • 独享锁:同一时间,只有一个线程能持有该锁。
  • 共享锁:同一时间,允许多个线程持有该锁。

4. 按是否可重复获取:可重入锁

  • 可重入锁:当一个线程已经持有某个锁时,再次请求获取该锁时不会被自己阻塞,而是直接获取(锁的计数器+1)。可以避免锁嵌套导致的死锁。

5. 按锁的量级:偏向锁 → 轻量级锁 → 重量级锁

这是 synchronized 的锁升级机制,JVM 为了提升锁性能,根据线程竞争的程度来动态调整适应,锁的升级是不可逆的。

  • 偏向锁:一段同步代码一直被一个线程所访问,那么该线程会自动获取锁;
  • 轻量级锁:当有第二个线程尝试获取偏向锁时,偏向锁会升级成轻量级锁,其他的线程会通过自旋的形式尝试获取锁;
  • 重量级锁:当锁为轻量级锁时,另一个线程自旋次数到达上限后还没有获取到锁,就会升级成重量级锁,其他申请的线程会进入阻塞。

6. 自旋锁 & 自适应自旋

自旋锁

当线程获取锁失败时,不立即阻塞挂起,而是循环重试(自旋)一段时间,看是否能获取到锁。

  • 优点:避免线程内核态 / 用户态切换的开销;
  • 缺点:自旋消耗 CPU 资源,若锁持有时间长,自旋会浪费 CPU。

自适应自旋

JDK 1.6 后引入,自旋次数不再固定,而是根据「前一次自旋的结果」「锁持有者的状态」动态调整:

  • 若前一次自旋成功获取锁,本次自旋次数增加;
  • 若前一次自旋失败,本次自旋次数减少甚至直接放弃自旋。

7. 锁优化:锁粗化 & 锁清除

这是 JVM 的自动优化手段,无需开发者手动操作。

  • 锁粗化:JVM将多个连续的加锁 / 解锁操作(如循环内的同步代码)扩展到整个操作序列的外部(循环外)合并为一次;
  • 锁清除:JVM通过分析,检测到某个同步锁保护的资源没有被多线程共享,则自动移除该锁。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 10:29:22

MIMO-OFDM通感一体化波形设计的实验验证与性能权衡分析

1. MIMO-OFDM通感一体化技术基础解析 通感一体化(ISAC)这个概念听起来高大上,但说白了就是让无线信号既能传数据又能当雷达用。想象一下你的手机基站不仅能给你发微信,还能顺便探测周围有没有无人机——这就是ISAC的魔力。而MIMO-OFDM作为5G的当家技术&…

作者头像 李华
网站建设 2026/6/10 15:33:43

荣品RD-RK3588开发板Android13开机自启动的SE策略与脚本配置详解

1. 理解荣品RD-RK3588开发板的自启动机制 荣品RD-RK3588开发板作为一款高性能嵌入式设备,在工业控制、智能终端等领域应用广泛。Android13系统在这类设备上的应用,往往需要实现特定程序的开机自启动功能。与普通Android手机不同,开发板的自启…

作者头像 李华
网站建设 2026/5/29 6:37:02

AI 辅助开发实战:基于 Java Web 的毕业设计选题系统设计与实现

背景痛点:传统选题系统为什么总“踩坑” 每年毕业季,教务老师最头疼的不是答辩,而是“抢选题”。 旧系统要么 Excel 满天飞,要么 JSPServlet 老项目,改一行代码得全量重启;需求临时加“学生可退选”&#…

作者头像 李华
网站建设 2026/6/10 11:50:42

避坑指南!YOLO26模型导出/推理常见问题,99%的开发者都踩过

聚焦工业落地场景(CPU部署、OpenVINO、端到端、x86/ARM跨平台),梳理了99%开发者踩过的15个核心问题,每个问题均包含「现象→根因→可操作解决方案→避坑小贴士」,覆盖从导出到推理的全流程,帮你跳过所有高频…

作者头像 李华
网站建设 2026/6/10 12:50:32

从零到一:RV1103/RV1106蓝牙开发实战中的依赖陷阱与解决方案

RV1103/RV1106蓝牙开发实战:从C库冲突到稳定连接的完整解决方案 嵌入式开发者在使用RV1103/RV1106平台构建蓝牙功能时,常常会遇到各种依赖库冲突问题。本文将深入分析uClibc与glibc兼容性问题,并提供从环境配置到功能验证的完整解决方案。 …

作者头像 李华
网站建设 2026/6/10 13:35:43

自动化专业毕业设计避坑指南:从选题到系统实现的技术路径解析

自动化专业毕业设计避坑指南:从选题到系统实现的技术路径解析 摘要:许多自动化专业学生在毕业设计中面临选题空泛、技术栈混乱、系统缺乏工程规范等痛点,导致项目难以落地或答辩表现不佳。本文从技术科普视角出发,梳理典型毕设场景…

作者头像 李华