0

0

Java中锁的分类有哪些 详解Java中的各种锁机制

穿越時空

穿越時空

发布时间:2025-06-20 14:21:06

|

805人浏览过

|

来源于php中文网

原创

java中的锁主要分为悲观锁与乐观锁、公平锁与非公平锁、可重入锁与不可重入锁、独占锁与共享锁等类型。1.悲观锁如synchronized和reentrantlock适用于写多场景,每次操作都加锁保证数据一致性;2.乐观锁通过版本号或cas实现,适用于读多写少的场景,提高吞吐量;3.公平锁按申请顺序获取锁避免饥饿现象,但性能较低,而非公平锁效率高但可能导致线程饥饿;4.可重入锁允许同一线程多次获取同一把锁,避免死锁,如synchronized和reentrantlock;5.独占锁一次只能被一个线程持有,而共享锁允许多个线程同时访问,如readwritelock的读锁;6.自旋锁通过循环等待锁释放,适用于锁持有时间短的场景;7.jvm还对锁进行了优化,引入了锁升级机制,包括偏向锁、轻量级锁和重量级锁,根据竞争激烈程度进行状态转换,以提升性能。

Java中锁的分类有哪些 详解Java中的各种锁机制

Java中的锁种类繁多,理解它们能帮助我们写出更高效、更可靠的并发程序。简单来说,可以从不同的维度进行分类,比如悲观锁/乐观锁、公平锁/非公平锁、可重入锁/不可重入锁、独占锁/共享锁等等。掌握这些锁的特性,才能在实际场景中选择最合适的锁,避免死锁和性能瓶颈。

Java中锁的分类有哪些 详解Java中的各种锁机制

悲观锁与乐观锁的本质区别和应用场景

Java中锁的分类有哪些 详解Java中的各种锁机制

悲观锁,顾名思义,总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。悲观锁适用于写操作非常多的场景,先加锁可以保证写操作时数据正确。

立即学习Java免费学习笔记(深入)”;

Java中锁的分类有哪些 详解Java中的各种锁机制

乐观锁则相对乐观,它假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回用户错误的信息,让用户决定如何去做。乐观锁的实现方式通常是使用版本号机制或者CAS算法。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式:CAS实现的。乐观锁适用于读多写的场景,这样可以提高程序的吞吐量。

公平锁与非公平锁的区别与选择

公平锁是指多个线程按照申请锁的顺序来获取锁,类似排队,先到先得。而非公平锁则允许线程“插队”,即后来的线程可能比先来的线程更快获取到锁。

Java中的ReentrantLock可以通过构造函数指定是否为公平锁。默认情况下,ReentrantLock是非公平锁。synchronized也是一种非公平锁。

公平锁的优点是避免了“饥饿”现象,每个线程都有机会获得锁。缺点是效率相对较低,因为需要维护一个等待队列,并且线程切换的开销也比较大。非公平锁的优点是效率高,吞吐量大,但缺点是可能导致某些线程长时间无法获取到锁,产生“饥饿”现象。

实际应用中,如果对公平性要求不高,优先选择非公平锁,以提高性能。如果需要保证每个线程都有机会执行,避免“饥饿”,则选择公平锁。

可重入锁与不可重入锁:理解锁的嵌套使用

可重入锁是指,当一个线程已经获取到锁之后,允许它再次获取该锁,而不需要释放之前的锁。这意味着同一个线程可以多次进入被该锁保护的代码块。

Java中的synchronized和ReentrantLock都是可重入锁。可重入锁避免了死锁的发生,例如:

public class ReentrantLockExample {
    ReentrantLock lock = new ReentrantLock();

    public void outer() {
        lock.lock();
        try {
            System.out.println("Outer method acquired lock");
            inner();
        } finally {
            lock.unlock();
            System.out.println("Outer method released lock");
        }
    }

    public void inner() {
        lock.lock();
        try {
            System.out.println("Inner method acquired lock");
        } finally {
            lock.unlock();
            System.out.println("Inner method released lock");
        }
    }

    public static void main(String[] args) {
        ReentrantLockExample example = new ReentrantLockExample();
        example.outer();
    }
}

如果ReentrantLock不是可重入锁,那么inner方法在尝试获取锁时,会因为锁已经被outer方法持有而阻塞,导致死锁。

Lumen5
Lumen5

一个在线视频创建平台,AI将博客文章转换成视频

下载

独占锁与共享锁:控制资源访问权限

独占锁(也称为互斥锁)是指一次只能被一个线程持有的锁。当一个线程获取了独占锁之后,其他线程必须等待该线程释放锁才能获取。Java中的synchronized和ReentrantLock都是独占锁。

共享锁是指可以被多个线程同时持有的锁。多个线程可以并发地读取被共享锁保护的资源,但如果需要修改资源,则必须获取独占锁。Java中的ReadWriteLock接口提供了读写锁的实现,读锁是共享锁,写锁是独占锁。

读写锁适用于读多写少的场景,可以提高程序的并发性能。多个线程可以同时读取数据,只有在写数据时才需要进行互斥。

深入理解自旋锁:优化短时间锁竞争场景

自旋锁是一种特殊的锁,它不会让线程进入阻塞状态,而是让线程循环等待锁的释放。当锁被其他线程持有时,尝试获取锁的线程会不断地循环检查锁是否可用,直到获取到锁为止。

自旋锁适用于锁的持有时间非常短的场景。如果锁的持有时间较长,自旋锁会导致线程一直占用CPU资源,造成性能浪费。

Java中并没有直接提供自旋锁的实现,但可以使用CAS算法来实现简单的自旋锁。例如:

public class SpinLock {
    private AtomicReference owner = new AtomicReference<>();

    public void lock() {
        Thread current = Thread.currentThread();
        while (!owner.compareAndSet(null, current)) {
            // 自旋等待
        }
    }

    public void unlock() {
        Thread current = Thread.currentThread();
        owner.compareAndSet(current, null);
    }
}

CAS算法的性能取决于CPU的架构和锁竞争的激烈程度。在高并发场景下,CAS算法可能会出现大量的冲突,导致性能下降。

锁升级:从偏向锁到重量级锁

为了提高锁的性能,JVM对锁进行了优化,引入了锁升级的概念。锁升级是指锁的状态会根据锁竞争的激烈程度进行升级,从低级别的锁到高级别的锁。

锁的级别从低到高依次为:偏向锁、轻量级锁、重量级锁。

  • 偏向锁:当一个线程访问同步块并获取锁时,会在对象头中记录该线程的ID。以后该线程再次进入同步块时,不需要进行任何同步操作,直接可以获取锁。偏向锁适用于只有一个线程访问同步块的场景。
  • 轻量级锁:当多个线程尝试获取同一个锁时,偏向锁会升级为轻量级锁。轻量级锁使用CAS算法来尝试获取锁,如果获取失败,则会自旋等待。轻量级锁适用于锁竞争不激烈的场景。
  • 重量级锁:当轻量级锁自旋等待一定次数后仍然无法获取锁,或者有其他线程已经持有锁时,轻量级锁会升级为重量级锁。重量级锁会让线程进入阻塞状态,等待锁的释放。重量级锁适用于锁竞争激烈的场景。

理解锁升级的过程,可以帮助我们更好地理解JVM的锁优化机制,并根据实际场景选择合适的锁。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1076

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

169

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1338

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

16

2026.01.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

502

2023.08.10

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

407

2023.08.14

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

9

2026.01.27

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

107

2026.01.26

edge浏览器怎样设置主页 edge浏览器自定义设置教程
edge浏览器怎样设置主页 edge浏览器自定义设置教程

在Edge浏览器中设置主页,请依次点击右上角“...”图标 > 设置 > 开始、主页和新建标签页。在“Microsoft Edge 启动时”选择“打开以下页面”,点击“添加新页面”并输入网址。若要使用主页按钮,需在“外观”设置中开启“显示主页按钮”并设定网址。

13

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.9万人学习

C# 教程
C# 教程

共94课时 | 7.6万人学习

Java 教程
Java 教程

共578课时 | 51.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号