Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >为什么StampedLock会导致CPU100%?

为什么StampedLock会导致CPU100%?

原创
作者头像
磊哥
发布于 2024-07-18 12:05:40
发布于 2024-07-18 12:05:40
1460
举报

StampedLock 是 Java 8 引入的一种高级的锁机制,它位于 java.util.concurrent.locks 包中。与传统的读写锁(ReentrantReadWriteLock)相比,StampedLock 提供了更灵活和更高性能的锁解决方案,尤其适用于读操作远多于写操作的场景。

1.特点展示

相比于 Java 中的其他锁,StampedLock 具有以下特点:

  1. 读写分离:StampedLock 支持读写分离,读锁和写锁可以同时被不同的线程持有,从而提高了并发性能。而 synchronized 和 ReentrantLock 则不支持读写分离,读操作和写操作会相互阻塞。
  2. 乐观读:StampedLock 支持乐观读,读操作不会阻塞写操作,只有在写操作发生时才会升级为悲观读。这种方式适用于读多写少的场景,可以提高读操作的并发性能。而 ReentrantReadWriteLock 则不支持乐观读。
  3. 不可重入:ReentrantLock 和 synchronized 都是可重入锁,而 StampedLock 的写锁是不可重入的。
  4. 性能优势:StampedLock 在多线程并发中的读多情况下有更好的性能,因为 StampedLock 获取乐观读锁时,不需要通过 CAS 操作来设置锁的状态,只是简单地通过测试状态即可。2.基本使用StampedLock 有三种读写方法:
  5. readLock:读锁,用于多线程并发读取共享资源。
  6. writeLock:写锁,用于独占写入共享资源。
  7. tryOptimisticRead:读乐观锁,用于在不阻塞其他线程的情况下尝试读取共享资源。

其中 readLock() 和 writeLock() 方法与 ReentrantReadWriteLock 的用法类似,而 tryOptimisticRead() 方法则是 StampedLock 引入的新方法,它用于非常短的读操作。

因此,我们在加锁时,可以使用性能更高的读乐观锁来替代传统的读锁,如果能加锁成功,则它可以和其他线程(即使是写操作)一起执行,也无需排队运行(传统读锁遇到写锁时需要排队执行),这样的话 StampedLock 的执行效率就会更高,它是使用如下:

代码语言:java
AI代码解释
复制
// 创建 StampedLock 实例
StampedLock lock = new StampedLock();
// 获取乐观读锁
long stamp = lock.tryOptimisticRead(); 
// 读取共享变量
if (!lock.validate(stamp)) { // 检查乐观读锁是否有效
    stamp = lock.readLock(); // 如果乐观读锁无效,则获取悲观读锁
    try {
        // 重新读取共享变量
    } finally {
        lock.unlockRead(stamp); // 释放悲观读锁
    }
}

// 获取悲观读锁
long stamp = lock.readLock(); 
try {
    // 读取共享变量
} finally {
    lock.unlockRead(stamp); // 释放悲观读锁
}

// 获取写锁
long stamp = lock.writeLock(); 
try {
    // 写入共享变量
} finally {
    lock.unlockWrite(stamp); // 释放写锁
}

使用乐观读锁的特性可以提高读操作的并发性能,适用于读多写少的场景。如果乐观读锁获取后,在读取共享变量前发生了写入操作,则 validate 方法会返回 false,此时需要转换为悲观读锁或写锁重新访问共享变量。

3.注意事项

在使用 StampedLock 时,需要注意以下几个问题:

  1. 不可重入性:StampedLock 的读锁和写锁都不支持重入,这意味着一个线程在获取了锁之后,不能再次获取同一个锁,所以在使用 StampedLock 时,一定要避免嵌套使用。public void runningTask() throws Exception{ final StampedLock lock = new StampedLock(); Thread thread = new Thread(()->{ // 获取写锁 lock.writeLock(); // 永远阻塞在此处,不释放写锁 LockSupport.park(); }); thread.start(); // 保证 thread 获取写锁 Thread.sleep(100); Thread thread2 = new Thread(()-> // 阻塞在悲观读锁 lock.readLock() ); thread2.start(); // 保证 thread2 阻塞在读锁 Thread.sleep(100); // 中断线程 thread2,导致 thread2 CPU 飙升 thread2.interrupt(); thread2.join(); }以上代码中,线程一先获取到锁,之后阻塞,并未释放锁,而线程二阻塞在 readLock() 读锁时,收到了中断请求 interrupt(),但并未正确处理中断异常,因此线程会陷入无限循环中,试图从中断状态中恢复,这就会导致 CPU 使用率一直飙升。课后思考如何避免 StampedLock CPU 100% 的问题?
  2. 死锁问题:使用 StampedLock 时,必须使用与获取锁时相同的 stamp 来释放锁,否则就会导致释放锁失败,从而导致死锁问题的发生。
  3. CPU 使用率飙升问题:如果 StampedLock 使用不当,具体来说,在 StampedLock 执行 writeLock 或 readLock 阻塞时,如果调用了中断操作,如 interrupt() 可能会导致 CPU 使用率飙升。这是因为线程接收到了中断请求,但 StampedLock 并没有正确处理中断信号,那么线程可能会陷入无限循环中,试图从中断状态中恢复,这可能会导致 CPU 使用率飙升。4.CPU 100%问题演示以下代码中线程 2 会导致 CPU 100% 的问题,如下代码所示:

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JDK8并发包新增StampedLock锁
StampedLock是并发包里面jdk8版本新增的一个锁,该锁提供了三种模式的读写控制,三种模式分别如下:
加多
2018/09/06
4140
并发设计模式实战系列(6):读写锁
今天为大家带来的是并发设计模式实战系列,第六章读写锁模式​​,废话不多说直接开始~
摘星.
2025/05/20
810
并发设计模式实战系列(6):读写锁
StampedLock,一种比读写锁更快的锁!
最近公司的事情比较多,拖了很久的书稿终于和猫大人一起在这个周末写完了,总体就一个字:累。剩下的就是对稿件的修修补补了,后面的进度就应该会很快了。前段时间原本想着续更【精通高并发系列】专题,一直没时间,所以,这个事情也被一直搁浅着。现在,书稿写完了,就有一些时间续更这个专题了。之前,我把【精通高并发系列】专题的文章整理成了一本电子书——《深入理解高并发编程》,全书内容如下所示。
冰河
2021/07/20
5920
比读写锁更快的 StampedLock
我们先回顾上一篇 ReentrantReadWriteLock 读写锁,为什么有了 ReentrantReadWriteLock,还要引入 StampLock?
码哥字节
2020/03/24
9280
深入理解java并发锁
确保线程安全最常见的做法是利用锁机制(Lock、sychronized)来对共享数据做互斥同步,这样在同一个时刻,只有一个线程可以执行某个方法或者某个代码块,那么操作必然是原子性的,线程安全的。
Java宝典
2021/01/14
4380
深入理解java并发锁
阿里四轮面试遭遇StampedLock,这么应对保拿offer!
读写锁允许多个线程同时读共享变量,适用于读多写少。 那在读多写少的场景中,有没有更快的技术方案呢?还真有,JDK在1.8提供StampedLock,其性能比读写锁还好。
JavaEdge
2021/04/25
3540
阿里四轮面试遭遇StampedLock,这么应对保拿offer!
Semaphore,ReadWriteLock,StampedLock
上面三个方法都是原子性的,并且这个原子性是由信号量模型实现放保证的,在java中信号量的实现是有类Semaphore实现的,下面看看下面代码,
小土豆Yuki
2021/01/04
4680
Semaphore,ReadWriteLock,StampedLock
高性能解决线程饥饿的利器 StampedLock
在 JDK 1.8 引入 StampedLock,可以理解为对 ReentrantReadWriteLock 在某些方面的增强,在原先读写锁的基础上新增了一种叫乐观读(Optimistic Reading)的模式。该模式并不会加锁,所以不会阻塞线程,会有更高的吞吐量和更高的性能。
码哥字节
2020/09/24
7010
高性能解决线程饥饿的利器 StampedLock
面试官:素有Java锁王称号的‘StampedLock’你知道吗?我:这什么鬼?
我们在上一篇写ReentrantReadWriteLock读写锁的末尾留了一个小坑,那就是读写锁因为写锁的悲观性,会导致 “写饥饿”,这样一来会大大的降低读写效率,而今天我们就来将此坑填之!填坑工具为:StampedLock,一个素有Java锁王称号的同步类,也是在 java.util.concurrent.locks 包中。
JavaBuild
2024/05/27
1290
面试官:素有Java锁王称号的‘StampedLock’你知道吗?我:这什么鬼?
高并发之Phaser、ReadWriteLock、StampedLock
Phaser是JDK7开始引入的一个同步工具类,适用于一些需要分阶段的任务的处理。它的功能与 CyclicBarrier和CountDownLatch有些类似,功能上与 CountDownLatch 和 CyclicBarrier类似但支持的场景更加灵活类似于一个多阶段的栅栏,并且功能更强大,我们来比较下这三者的功能:
用户1289394
2021/03/11
4220
高并发之Phaser、ReadWriteLock、StampedLock
字节面试:说说Java中的锁机制?
Java 中的锁(Locking)机制主要是为了解决多线程环境下,对共享资源并发访问时的同步和互斥控制,以确保共享资源的安全访问。
磊哥
2024/05/13
1670
字节面试:说说Java中的锁机制?
腾讯面试:什么锁比读写锁性能更高?
在并发编程中,读写锁 ReentrantReadWriteLock 的性能已经算是比较高的了,因为它将悲观锁的粒度分的更细,在它里面有读锁和写锁,当所有操作为读操作时,并发线程是可以共享读锁同时运行的,这样就无需排队执行了,所以执行效率也就更高。
磊哥
2024/05/15
1300
深入剖析Java并发库(JUC)之StampedLock的应用与原理
StampedLock是Java 8引入的一种新的锁机制,它提供了乐观读锁和悲观读写锁的能力。与传统的ReentrantLock和ReentrantReadWriteLock相比,StampedLock在并发性能上有了显著的提升。这是因为它支持一种称为“乐观读”的锁策略,该策略允许多个线程同时读取共享资源,而无需阻塞或等待其他线程的锁释放。
公众号:码到三十五
2024/03/24
2931
深入剖析Java并发库(JUC)之StampedLock的应用与原理
ReentrantLock、ReentrantReadWriteLock、StampedLock
读写锁定义: 一个资源能够被多个读线程访问,或者被一个写线程访问,但是不能同时存在读写线程。
鱼找水需要时间
2023/02/16
3770
ReentrantLock、ReentrantReadWriteLock、StampedLock
JDK内置锁深入探究
锁有多种分类形式,比如公平锁与非公平锁、可重入锁与非重入锁、独享锁与共享锁、乐观锁与悲观锁、互斥锁与读写锁、自旋锁、分段锁和偏向锁/轻量级锁/重量级锁。
赛先生和泰先生
2022/04/20
5380
JDK内置锁深入探究
ReadWriteLock 和 StampedLock
在多线程编程中,对于共享资源的访问控制是一个非常重要的问题。在并发环境下,多个线程同时访问共享资源可能会导致数据不一致的问题,因此需要一种机制来保证数据的一致性和并发性。
疯狂的KK
2023/08/14
2080
ReadWriteLock 和 StampedLock
Java Review - 并发编程_StampedLock锁探究
StampedLock是并发包里面JDK8版本新增的一个锁,该锁提供了三种模式的读写控制, 当调用获取锁的系列函数时,会返回一个long 型的变量,我们称之为戳记(stamp),这个戳记代表了锁的状态。
小小工匠
2021/12/06
1690
【原创】Java并发编程系列19 | JDK8新增锁StampedLock
StampedLock是 JDK1.8 版本中在 J.U.C 并发包里新增的一个锁,StampedLock是对读写锁ReentrantReadWriteLock的增强,优化了读锁、写锁的访问,更细粒度控制并发。这篇文章就来介绍一下StampedLock,分为如下几个问题:
java进阶架构师
2020/04/24
5410
【原创】Java并发编程系列19 | JDK8新增锁StampedLock
简单了解下Java中锁的概念和原理
Java提供了很多种锁的接口和实现,通过对各种锁的使用发现理解锁的概念是很重要的。
codetrend
2024/06/29
1350
java中Locks的使用
之前文章中我们讲到,java中实现同步的方式是使用synchronized block。在java 5中,Locks被引入了,来提供更加灵活的同步控制。
程序那些事
2020/07/08
5130
相关推荐
JDK8并发包新增StampedLock锁
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档