一文速通Java的各种锁和锁的分类(面试实用干货)

写在前面

        本文选题来源于各中大厂开发岗面试时的相关“八股”问题,全文干货无废话,适合具有一定Java语言基础的技术开发者阅读。


1. 按是否阻塞

(1)互斥锁(Mutex)

        线程在获取锁失败时主动放弃CPU,进入阻塞状态,等待锁释放后被唤醒。Java的重量级锁依赖互斥锁实现(在下文中将会提到)。
        互斥锁的阻塞与唤醒实现依赖操作系统的线程调度,需要消耗性能资源。高并发的情况下线程频繁阻塞与唤醒将影响程序性能。

(2)自旋锁(Spinlock)

        线程在获取锁失败时循环重试(自旋),不放弃CPU不阻塞,直到锁可用。适用于锁持有时间极短(如计数器更新)、竞争不激烈的程序或核心数较多的系统。但如果长时间自旋,相当于让CPU“空转”,因此也会产生性能问题,Java为此设计了默认的自旋次数,自旋次数耗尽则锁升级,详情请见下文。


2. 按照锁的等级

 (1)偏向锁(Biased Locking)

        目的:优化单线程重复访问同步块的场景,避免无竞争时的同步操作。

        实现:首次获取锁时,JVM在对象头中记录偏向线程ID。同一线程后续进入同步块(同步块可以简单理解为加锁的对象)时,直接检查线程ID是否匹配即可。

        锁升级/锁膨胀(注意不是锁粗化,锁粗化是JVM对锁粒度的优化):当其他线程尝试获取锁时,偏向锁升级为轻量级锁。

(2)轻量级锁(Lightweight Locking)

        目的:解决多线程交替访问同步块但无并发竞争的场景,避免产生线程阻塞(线程的阻塞和唤醒需要消耗性能资源)。

        实现:线程通过CAS操作尝试将对象头中的标记替换为指向栈中锁记录的指针。若成功,线程获得锁;若失败(存在竞争),触发自旋锁循环重试。

        锁升级:自旋次数超过默认次数(JDK 6后自适应调整)后或有多个线程(超过1个)在自旋等待同一个锁时,锁升级为重量级锁,防止因为自旋而过度消耗CPU。

(3)重量级锁(Heavyweight Locking

        目的:处理高并发竞争场景,确保线程互斥访问。

        实现:基于操作系统的互斥量(Mutex)和条件变量(Condition Variable)。未获取锁的线程被阻塞,进入等待队列,由操作系统调度唤醒。

        性能代价:涉及用户态与内核态切换,上下文开销大,高并发时性能显著下降。

 需要注意的是,锁的等级在Java对象结构-对象头-Mark Word 中被明确指定。

图片来源:【Java并发】月薪30K必须知道的Java锁机制_哔哩哔哩_bilibili


3. 按照互斥程度(互斥锁的子类)

        排它锁(写锁):获得锁的资源在被锁释放之前无法添加其他任何互斥锁; 

        共享锁(读锁):获得锁的资源允许被添加其他的共享锁但无法添加排它锁


4. 按照公平性

        公平锁:需要手动开启,例如 ReentrantLock(true)。开启后将按线程请求锁的顺序分配锁(先到先得),并发性能较低,仅适用于需要严格指定顺序的业务逻辑,例如实时排名、交易订单等。

        非公平锁:默认使用非公平锁,例如ReentrantLock()、ReentrantLock(false)、synchronized。性能和执行效率优先,允许线程插队获取锁(刚释放锁的线程可能直接再次获取)。


5. 按照机制(悲观锁和乐观锁)

悲观锁乐观锁在数据库中也有着广泛的应用,本文只讨论Java。

(1)悲观锁(Pessimistic Lock)

        悲观锁在访问资源前先加锁。确保数据的强一致性。适用于对安全性和一致性要求高、写多读少、锁竞争激烈的场景。例如,银行转账、库存扣减等。

        Java的synchronized关键字和ReentrantLock都是悲观锁。

(2)乐观锁(Optimistic Lock

        个人理解乐观锁更类似于一种机制,而不是一种真正的“锁”,有的时候会把乐观锁的运用也称为“无锁操作”。乐观锁允许直接操作数据,但在提交时检查是否发生冲突。冲突则重新执行。乐观锁通过检查前后数据/版本号是否一致,来确定是否发生冲突。适用于高并发、读多写少的场景。例如,点赞统计,状态标记等。

        乐观锁的实现核心是CAS操作。CAS(Compare And Swap)是一种硬件级原子操作,通过比较比较内存值与预期值,若一致则更新为新值。CAS是Java原子类实现的基础。


  6. 其他锁分类

        可重入锁:允许某一线程多次获得锁。

        可中断锁:等待时可中断。

        超时获得锁:在规定时间内没有获得锁则放弃。

        ReentrantLock实现了可中断锁、超时获得锁,synchronized和ReentrantLock都是可重入锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值