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

简介: 曾几何时,面试官问: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自旋循环等待获取锁。

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

相关文章
|
8月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
417 1
|
8月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
305 6
|
8月前
|
安全 前端开发 Java
从反射到方法句柄:深入探索Java动态编程的终极解决方案
从反射到方法句柄,Java 动态编程不断演进。方法句柄以强类型、低开销、易优化的特性,解决反射性能差、类型弱、安全性低等问题,结合 `invokedynamic` 成为支撑 Lambda 与动态语言的终极方案。
321 0
|
9月前
|
SQL Java 数据库
2025 年 Java 从零基础小白到编程高手的详细学习路线攻略
2025年Java学习路线涵盖基础语法、面向对象、数据库、JavaWeb、Spring全家桶、分布式、云原生与高并发技术,结合实战项目与源码分析,助力零基础学员系统掌握Java开发技能,从入门到精通,全面提升竞争力,顺利进阶编程高手。
1303 2
|
9月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
600 100
|
8月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
404 1
|
8月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
379 1
|
9月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
386 0
|
9月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
562 16