跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

Java 常见锁类型及适用场景详解

系统梳理了 Java 中的锁机制,涵盖内置锁 synchronized 与显式锁 Lock 接口。详细解析了可重入锁、乐观锁与悲观锁、公平与非公平锁、读写锁及锁升级原理。结合实战选型指南,针对简单互斥、高并发读写、任务排队等不同场景推荐合适的锁方案,帮助开发者优化并发性能与线程安全。

CodeArtist发布于 2026/3/30更新于 2026/9/988 浏览
Java 常见锁类型及适用场景详解

一、基础分类(按实现方式)

这是最核心的分类维度,直接决定锁的使用方式和核心能力。

1. 内置锁(synchronized)- 隐式锁
核心定义

Java 关键字,JVM 层面实现的隐式锁(无需手动释放),是最基础、使用最广泛的锁。JDK1.6 后引入「锁升级」机制,性能大幅提升。

核心特点
  • 可重入、默认非公平锁;
  • 自动加锁 / 解锁(方法 / 代码块执行完自动释放,无需手动处理);
  • 底层依赖对象头的 Mark Word + 监视器锁(ObjectMonitor);
  • 支持锁升级(偏向锁→轻量级锁→重量级锁),适配不同并发场景。
适用场景
  • 简单互斥场景(如方法 / 代码块的线程安全);
  • 并发度不高、代码简洁性优先的场景;
  • 不需要灵活特性(如可中断、超时获取锁)的场景;
  • 绝大多数普通业务场景(JVM 优化后性能接近显式锁)。
代码示例
public class SynchronizedDemo {
    // 1. 实例方法锁(对象锁):锁当前实例对象
    public synchronized void objectLock() {
        System.out.println(Thread.currentThread().getName() + "获取对象锁");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {}
    }

    // 2. 静态方法锁(类锁):锁当前类的 Class 对象
    public static synchronized void classLock() {
        System.out.println(Thread.currentThread().getName() + "获取类锁");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {}
    }

    // 3. 代码块锁:自定义锁对象(灵活度最高)
    private final Object lockObj =  ();
       {
         (lockObj) {
            System.out.println(Thread.currentThread().getName() + );
             {
                Thread.sleep();
            }  (InterruptedException e) {}
        }
    }

        {
            ();
        
         (demo::objectLock, ).start();
         (demo::objectLock, ).start();
    }
}
new
Object
public
void
blockLock
()
synchronized
"获取代码块锁"
try
100
catch
public
static
void
main
(String[] args)
SynchronizedDemo
demo
=
new
SynchronizedDemo
// 竞争同一对象锁,串行执行
new
Thread
"线程 1"
new
Thread
"线程 2"
2. 显式锁(Lock 接口)- 手动锁
核心定义

JUC 包下 java.util.concurrent.locks.Lock 接口的实现类,手动加锁 / 释放锁(需在 finally 中释放,避免死锁),是 synchronized 的补充和增强。

核心实现类 & 特点
实现类核心特性
ReentrantLock可重入、支持公平 / 非公平、可中断、超时获取锁
ReentrantReadWriteLock读写分离(读共享、写独占)、可重入
StampedLock支持乐观读、读写锁、写锁,性能优于读写锁
适用场景
  • 需要灵活锁控制(如可中断、超时获取锁、公平锁)的场景;
  • 读多写少的高并发场景(选 ReentrantReadWriteLock/StampedLock);
  • 高并发、需要精细控制锁生命周期的场景。
代码示例(ReentrantLock)
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {
    // 公平锁(按请求顺序获取),默认非公平锁(性能更高)
    private static final ReentrantLock lock = new ReentrantLock(true);

    public static void doTask() {
        // 1. 加锁(可替换为 lockInterruptibly():可中断锁)
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "获取锁");
            // 模拟业务操作
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // 恢复中断状态
        } finally {
            // 2. 释放锁(必须放 finally,否则死锁)
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
                System.out.println(Thread.currentThread().getName() + "释放锁");
            }
        }
    }

    public static void main(String[] args) {
        new Thread(ReentrantLockDemo::doTask, "线程 A").start();
        new Thread(ReentrantLockDemo::doTask, "线程 B").start();
    }
}

二、进阶分类(按锁的核心特性)

基于锁的行为和并发特性分类,帮你理解锁的底层逻辑和适用场景。

1. 可重入锁 vs 不可重入锁
类型定义示例适用场景
可重入锁同一线程可多次获取同一把锁,不会死锁synchronized、ReentrantLock所有业务场景(递归调用、同一线程多次操作共享资源)
不可重入锁同一线程多次获取同一锁会死锁自定义简单自旋锁(未处理重入)极少使用(仅严格限制锁获取次数的特殊场景)
可重入锁示例(synchronized 递归调用)
public class ReentrantDemo {
    public synchronized void outer() {
        System.out.println("外层方法获取锁");
        inner(); // 同一线程再次获取同一锁,无死锁
    }

    public synchronized void inner() {
        System.out.println("内层方法获取锁");
    }

    public static void main(String[] args) {
        new ReentrantDemo().outer(); // 正常执行,无死锁
    }
}
2. 乐观锁 vs 悲观锁

这是并发设计思想的分类,而非具体锁实现。

类型核心思想实现方式适用场景
悲观锁假设必有竞争,先锁后执行synchronized、ReentrantLock高冲突、写多读少(如库存扣减、转账)
乐观锁假设无竞争,先执行后检测CAS(Atomic 类)、版本号低冲突、读多写少(如计数器、缓存更新)
乐观锁示例(CAS 实现)
import java.util.concurrent.atomic.AtomicInteger;

public class OptimisticLockDemo {
    // CAS 是乐观锁的核心实现
    private static final AtomicInteger count = new AtomicInteger(0);

    // 原子自增(无锁,冲突时重试)
    public static void increment() {
        count.incrementAndGet();
    }

    public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) increment();
        };
        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("最终计数:" + count.get()); // 2000(线程安全)
    }
}
3. 公平锁 vs 非公平锁
类型定义示例适用场景
公平锁按请求顺序获取锁,先到先得ReentrantLock(true)对公平性要求高(如任务排队、避免线程饥饿)
非公平锁不按顺序,线程可插队获取锁synchronized、ReentrantLock()大部分场景(优先性能,容忍轻微饥饿)
4. 读写锁(ReentrantReadWriteLock)- 共享 + 独占锁
核心定义

将锁拆分为「读锁(共享锁)」和「写锁(独占锁)」,核心规则:

  • 读 - 读共享:多个线程可同时获取读锁;
  • 读 - 写互斥:读锁和写锁不能同时持有;
  • 写 - 写互斥:多个线程不能同时获取写锁。
适用场景

读多写少的场景(如缓存、配置读取、商品详情页、数据查询),相比普通独占锁,能大幅提升读并发效率。

代码示例
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
    private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private static final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
    private static final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
    private static int cacheData = 0;

    // 模拟缓存数据
    // 读操作(共享锁,多线程同时执行)
    public static void readCache() {
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "读取缓存:" + cacheData);
            Thread.sleep(200); // 模拟读耗时
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            readLock.unlock();
        }
    }

    // 写操作(独占锁,串行执行)
    public static void updateCache(int newData) {
        writeLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "更新缓存:" + newData);
            cacheData = newData;
            Thread.sleep(200); // 模拟写耗时
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            writeLock.unlock();
        }
    }

    public static void main(String[] args) {
        // 5 个读线程(可同时执行,并发效率高)
        for (int i = 0; i < 5; i++) {
            new Thread(ReadWriteLockDemo::readCache, "读线程" + i).start();
        }
        // 1 个写线程(独占,所有读线程等待)
        new Thread(() -> updateCache(100), "写线程").start();
    }
}
5. synchronized 的锁升级(偏向锁→轻量级锁→重量级锁)

JDK1.6 为优化 synchronized 引入的自适应锁机制,锁级别从低到高升级(不可逆),适配不同并发场景:

锁类型核心特点适用场景
偏向锁锁偏向第一个线程,无竞争时零开销单线程执行同步代码(如初始化资源)
轻量级锁多线程交替竞争,CAS 自旋获取锁少量线程(2-3 个)交替执行
重量级锁多线程激烈竞争,线程阻塞(OS 层面)大量线程同时竞争锁
6. 自旋锁 vs 阻塞锁
类型定义示例适用场景
自旋锁获取锁失败时循环重试(自旋),不阻塞CAS、synchronized 轻量级锁锁持有时间短、低冲突(如简单变量更新)
阻塞锁获取锁失败时线程阻塞,释放 CPUsynchronized 重量级锁、ReentrantLock锁持有时间长、高冲突(如复杂业务逻辑)
7. 分段锁(ConcurrentHashMap JDK1.7)
核心定义

将数据拆分为多个「段(Segment)」,每个段独立加锁,不同段的操作互不阻塞,并发度 = 段数(默认 16)。

适用场景

JDK1.7 的 ConcurrentHashMap(JDK1.8 后用 CAS+Synchronized 替代),适用于高并发读写 Map 的场景。


三、实战选型指南(核心)

业务场景推荐锁类型选型原因
简单互斥、代码简洁synchronized隐式锁,无需手动释放,JVM 优化优异
可中断 / 超时 / 公平锁ReentrantLock支持灵活的锁控制特性
读多写少(缓存 / 查询)ReentrantReadWriteLock/StampedLock读共享,大幅提升读并发效率
低冲突、简单变量更新CAS(AtomicInteger/AtomicLong)无锁,性能最高,避免自旋消耗
高冲突、写多读少(转账)synchronized/ReentrantLock悲观锁,避免高冲突下的 CAS 自旋 CPU 开销
公平性要求高(任务排队)ReentrantLock(true)按请求顺序获取锁,避免线程饥饿
高并发 Map 操作ConcurrentHashMapJDK1.8 用 CAS+Synchronized,兼顾性能和安全性

总结

关键点回顾
  1. 基础核心:synchronized(简单、通用)和 Lock 接口(灵活、高级)是 Java 锁的两大基石,前者适用于普通场景,后者适用于需要灵活控制的场景;
  2. 特性选型:读多写少选读写锁,低冲突选乐观锁 / CAS,高冲突选悲观锁,公平性要求高选公平锁;
  3. 性能原则:优先选择「开销低」的锁(如偏向锁、CAS),高冲突场景才用「高开销」的阻塞锁(如重量级锁);
  4. 实战建议:90% 的普通业务场景用 synchronized 即可,仅在需要可中断、超时、读写分离时才用 Lock 接口实现类。

目录

  1. 一、基础分类(按实现方式)
  2. 1. 内置锁(synchronized)- 隐式锁
  3. 核心定义
  4. 核心特点
  5. 适用场景
  6. 代码示例
  7. 2. 显式锁(Lock 接口)- 手动锁
  8. 核心定义
  9. 核心实现类 & 特点
  10. 适用场景
  11. 代码示例(ReentrantLock)
  12. 二、进阶分类(按锁的核心特性)
  13. 1. 可重入锁 vs 不可重入锁
  14. 可重入锁示例(synchronized 递归调用)
  15. 2. 乐观锁 vs 悲观锁
  16. 乐观锁示例(CAS 实现)
  17. 3. 公平锁 vs 非公平锁
  18. 4. 读写锁(ReentrantReadWriteLock)- 共享 + 独占锁
  19. 核心定义
  20. 适用场景
  21. 代码示例
  22. 5. synchronized 的锁升级(偏向锁→轻量级锁→重量级锁)
  23. 6. 自旋锁 vs 阻塞锁
  24. 7. 分段锁(ConcurrentHashMap JDK1.7)
  25. 核心定义
  26. 适用场景
  27. 三、实战选型指南(核心)
  28. 总结
  29. 关键点回顾

更多推荐文章

查看全部
  • Python 处理 Markdown 文件:生成、转换与解析实战
  • EasyProfiler C++ 性能分析库配置与使用指南
  • 基于 llama.cpp 在单 GPU 上高效部署 Qwen3.5 及股票筛选实战
  • 使用 Gitee AI Serverless API 与 Cursor 搭建 DeepSeek 对话应用
  • Docker 部署 Music-Tag-Web 音乐标签编辑工具
  • Spring Web MVC 入门:注解用法、参数传递与 Postman 测试
  • RabbitMQ RPC 通信模式详解
  • Mac Big Sur 使用 Docker 运行 OpenCode 实现 AI 自动化开发流程
  • 融合选择性卷积与残差结构的 SKResNet 架构详解
  • 5 款主流 AI 应用开发工具对比与选型建议
  • 字节跳动 Java 后端开发面试题精选
  • Power BI 集成 Python 实现高级数据可视化与分析
  • 网络安全体系解析:三大方向与学习路线指南
  • Shannon:基于 AI 的自动化 Web 应用漏洞检测工具
  • 国内热门 AI 绘画工具盘点(上)
  • Llama 3-8B-Instruct 在昇腾 NPU 上的 SGLang 性能实测
  • Node.js 18+ 安装教程
  • VSCode Copilot 无法登录原因排查与恢复指南
  • MySQL 复杂查询:连接、嵌套与集合操作
  • 初识 LangChain 与大语言模型基础

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online