JAVA并发编程-一文看懂全部锁机制

本文涉及的产品
云原生网关 MSE Higress,422元/月
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 曾几何时,面试官问:java都有哪些锁?小白,一脸无辜:用过的有synchronized,其他不清楚。面试官:回去等通知!今天我们庖丁解牛说说,各种锁有什么区别、什么场景可以用,通俗直白的分析,让小白再也不怕面试官八股文拷打。

曾几何时,面试官问:java都有哪些锁?小白,一脸无辜:用过的有synchronized,其他不清楚。面试官:回去等通知!

    今天我们庖丁解牛说说,各种锁有什么区别、什么场景可以用,通俗直白的分析,让小白再也不怕面试官八股文拷打。

    之前的文章说过《JAVA并发编程synchronized全能王的原理》、以及《JAVA并发编程JUC包之CAS原理》,synchronized、CAS都是常见的锁。那么锁的类型是如何划分的呢?

一、按特性划分

1.1 悲观锁和乐观锁

按线程访问共享资源时,要不要锁住同步资源来定义。比如synchronized就是悲观锁,数据库的行锁、表锁都是悲观锁。

CAS就是乐观锁,数据库版本号机制也是乐观锁。

    悲观锁的应用场景:大量更新修改操作,使用悲观锁,可以保证数据强一致性。

    乐观锁的应用场景:读多写少的场景,提高吞吐量。

1.2 可重入锁和不可重入锁

一个线程,是否可以重复获取同一把锁。比如synchronized、ReentrantLock是可重入锁,可以重复加锁。可重入锁在加锁N次后,解锁就需要进行N次解锁。效率较低,但是好处是可以避免死锁,因为在方法内部递归,如果使用普通锁,可能会出现死锁。而可重入锁支持线程重复进入同一个代码块。

1.3 公平锁和非公平锁

多线程竞争同一个锁时,是否需要排队,以及是否可以插队。

    公平锁,就是多个线程按顺序申请锁。比如new ReentrantLock(true),就是公平锁。

    非公平锁,就是多个线程获取锁不是按申请顺序获得,可以插队。比如new ReentrantLock(false), synchronized。

非公平锁的缺点,就是可能导致线程饥饿现象,某个线程或多个线程由于优先级较低,长期被其他优先级较高的线程插队抢夺锁资源,导致无法获得CPU执行。

1.4 独享锁和共享锁

    独享锁、共享锁,也叫排它锁和非排它锁。

依据是:多个线程能否同时共享同一个锁。

   独享锁=排它锁,比如synchronized、ReentrantLock,ReentrantReadWriteLock的write写锁,都是独享锁。

   共享锁=非排它锁,比如ReentrantReadWriteLock的readLock读锁就是共享锁。

   也有人说,互斥锁,其实也是独享锁。有人说读写锁,对应的就是ReentrantReadWriteLock。

二、按上锁方式划分

2.1 隐式锁和显式锁

    按是否显式的执行加锁和解锁过程。比如synchronized,我们使用它后,不需要显式的解锁。而JUC包的ReentrantLock就需要显式的lock(),unlock().

三、其他类型锁

自旋锁,锁获取失败后, 线程不会阻塞,而是循环尝试获取锁直至成功。比如CAS、轻量级锁都是自旋锁。

分段锁,将锁的粒度划分更细,当一个线程对一段数据进行加锁访问时,其他段的数据可以被其他线程同时访问。比如concurrentHashMap,就是使用锁分段技术。

四、synchronized的锁状态

无锁、偏向锁、轻量级锁、重量级锁四种状态。其中JDK1.6新增了偏向锁和轻量级锁。这四种状态是随着多线程竞争,逐级升级的状态,不可逆不可降级。是JVM特定给synchronized提升效率而做的优化。

   偏向锁:就是只有一个线程访问共享资源时,不会加锁,只是记录当前持有锁资源线程的锁类型,然后该线程每次执行这部分共享资源,都只是判断是否持有锁,以及当前锁类型。

   轻量级锁:在偏向锁的基础上,如果当前有两个线程在交替竞争锁,这时候将锁状态膨胀为【轻量级锁】。同时竞争失败的线程,不阻塞,用CAS自旋循环等待获取锁。

   重量级锁:轻量级锁,自旋一定次数后,膨胀为重量级锁,竞争失败的线程直接进入阻塞状态,等持有锁的线程释放锁后再唤醒。

目录
打赏
0
4
6
1
109
分享
相关文章
理解的Java中SPI机制
本文深入解析了JDK提供的Java SPI(Service Provider Interface)机制,这是一种基于接口编程、策略模式与配置文件组合实现的动态加载机制,核心在于解耦。文章通过具体示例介绍了SPI的使用方法,包括定义接口、创建配置文件及加载实现类的过程,并分析了其原理与优缺点。SPI适用于框架扩展或替换场景,如JDBC驱动加载、SLF4J日志实现等,但存在加载效率低和线程安全问题。
理解的Java中SPI机制
深入理解Java锁升级:无锁 → 偏向锁 → 轻量级锁 → 重量级锁(图解+史上最全)
锁状态bits1bit是否是偏向锁2bit锁标志位无锁状态对象的hashCode001偏向锁线程ID101轻量级锁指向栈中锁记录的指针000重量级锁指向互斥量的指针010尼恩提示,讲完 如减少锁粒度、锁粗化、关闭偏向锁(-XX:-UseBiasedLocking)等优化手段 , 可以得到 120分了。如减少锁粒度、锁粗化、关闭偏向锁(-XX:-UseBiasedLocking)等‌。JVM锁的膨胀、锁的内存结构变化相关的面试题,是非常常见的面试题。也是核心面试题。
深入理解Java锁升级:无锁 → 偏向锁 → 轻量级锁 → 重量级锁(图解+史上最全)
Java 中 .length 的使用方法:深入理解 Java 数据结构中的长度获取机制
本文深入解析了 Java 中 `.length` 的使用方法及其在不同数据结构中的应用。对于数组,通过 `.length` 属性获取元素数量;字符串则使用 `.length()` 方法计算字符数;集合类如 `ArrayList` 采用 `.size()` 方法统计元素个数。此外,基本数据类型和包装类不支持长度属性。掌握这些区别,有助于开发者避免常见错误,提升代码质量。
51 1
k8s的出现解决了java并发编程胡问题了
Kubernetes通过提供自动化管理、资源管理、服务发现和负载均衡、持续交付等功能,有效地解决了Java并发编程中的许多复杂问题。它不仅简化了线程管理和资源共享,还提供了强大的负载均衡和故障恢复机制,确保应用程序在高并发环境下的高效运行和稳定性。通过合理配置和使用Kubernetes,开发者可以显著提高Java应用程序的性能和可靠性。
82 31
注解的艺术:Java编程的高级定制
注解是Java编程中的高级特性,通过内置注解、自定义注解及注解处理器,可以实现代码的高度定制和扩展。通过理解和掌握注解的使用方法,开发者可以提高代码的可读性、可维护性和开发效率。在实际应用中,注解广泛用于框架开发、代码生成和配置管理等方面,展示了其强大的功能和灵活性。
73 25
在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境
以上内容是一个简单的实现在Java后端中通过DockerClient操作Docker生成python环境并执行代码,最后销毁的案例全过程,也是实现一个简单的在线编程后端API的完整流程,你可以在此基础上添加额外的辅助功能,比如上传文件、编辑文件、查阅文件、自定义安装等功能。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境
|
2月前
|
Java静态代码块深度剖析:机制、特性与最佳实践
在Java中,静态代码块(或称静态初始化块)是指类中定义的一个或多个`static { ... }`结构。其主要功能在于初始化类级别的数据,例如静态变量的初始化或执行仅需运行一次的初始化逻辑。
78 4
课时6:Java编程起步
课时6:Java编程起步,主讲人李兴华。课程摘要:介绍Java编程的第一个程序“Hello World”,讲解如何使用记事本或EditPlus编写、保存和编译Java源代码(*.java文件),并解释类定义、主方法(public static void main)及屏幕打印(System.out.println)。强调类名与文件名一致的重要性,以及Java程序的编译和执行过程。通过实例演示,帮助初学者掌握Java编程的基本步骤和常见问题。
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
6月前
|
Java中的多线程编程入门
【10月更文挑战第29天】在Java的世界中,多线程就像是一场精心编排的交响乐。每个线程都是乐团中的一个乐手,他们各自演奏着自己的部分,却又和谐地共同完成整场演出。本文将带你走进Java多线程的世界,让你从零基础到能够编写基本的多线程程序。
64 1
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等