Bug:StampedLock的中断问题导致CPU爆满

简介:

StampedLock作为JAVA8中出现的新型锁,很可能在大多数场景都可以替代ReentrantReadWriteLock。它对于读/写都提供了四个接口(换成write为写锁):

  • readLock()
  • tryReadLock()
  • tryReadLock(long time, TimeUnit unit)
  • readLockInterruptibly()

这几个方法对应的语义为:

  • 获取读锁(阻塞,不响应中断)
  • 获取读锁(立即)
  • 限时获取读锁(响应中断)
  • 获取读锁(阻塞,响应中断)

然而在readLock方法(即不响应中断)中存在问题(write的版本也是),观察CPU使用率,执行以下代码:
01 public class TestStampedLock {
02     public static void main(String[] args) throws InterruptedException{
03     final StampedLock lock = new StampedLock();
04     new Thread(){
05        public void run(){
06        long readLong = lock.writeLock();
07        LockSupport.parkNanos(6100000000L);
08        lock.unlockWrite(readLong);
09      }
10     }.start();
11     Thread.sleep(100);
12     forint i = 0; i < 3; ++i)
13        new Thread(new OccupiedCPUReadThread(lock)).start();
14     }
15     private static class OccupiedCPUReadThread implements Runnable{
16         private StampedLock lock;
17         public OccupiedCPUReadThread(StampedLock lock){
18             this.lock = lock;
19         }
20         public void run(){
21             Thread.currentThread().interrupt();
22             long lockr = lock.readLock();
23             System.out.println(Thread.currentThread().getName() + " get read lock");
24             lock.unlockRead(lockr);
25         }
26     }
27 }
先开启一个线程获取写锁并保持6秒,再开启三个带着中断状态的线程去获取读锁(readLock方法),结果是3个核心被占据了近6秒。
原因在于没有使用 保存/复原中断状态的机制,通过hack源码,插入保存中断和返回前恢复中断的相关代码即可修复:
1 boolean interrupted = false;
1 if(interrupted)
2     Thread.currentThread().interrupt();
3 return ns;
1 if(Thread.interrupted()){
2     if(interruptible)
3         return cancelWaiter(node, p, true);
4     else
5         interrupted = true;
6 }
相关文章
|
6月前
|
存储 Ruby 内存技术
【机组期末速成】CPU的结构与功能|CPU结构|指令周期概述|指令流水线|中断系统
【机组期末速成】CPU的结构与功能|CPU结构|指令周期概述|指令流水线|中断系统
244 1
|
3月前
|
Java 编译器 Linux
JVM/编译器/CPU,究竟谁是卧底?一个曾经困扰我一个月的 bug
任何复杂的系统都可能因为一个小小的疏漏而无法运转,本文记录了一个困扰作者一个月的 bug 最终拨云见日的过程。
|
4月前
|
消息中间件 前端开发 NoSQL
为什么StampedLock会导致CPU100%?
为什么StampedLock会导致CPU100%?
50 9
|
6月前
|
资源调度 调度 UED
CPU执行系统调用时发生中断,操作系统还能切回中断前的系统调用继续执行吗?
系统调用服务例程在执行过程中,通常不会被中断。系统调用服务例程的执行是一个原子操作,即在执行期间不会被中断。这是为了确保在系统调用服务例程执行期间对内核数据结构的一致性和完整性。
|
Arthas NoSQL Java
线上服务器CPU100%的真相排查【Bug利器Arthas】
这起CPU100%的事故,由某个客户演示的bug暴露出来,气氛比较尴尬....
750 0
线上服务器CPU100%的真相排查【Bug利器Arthas】
|
缓存 编译器 Linux
CPU中断控制和并发处理的内核解析
CPU中断控制和并发处理的内核解析
CPU中断控制和并发处理的内核解析
|
Arthas 缓存 Kubernetes
JFR定位由于可能的JDK11的bug导致Log4j2 CPU占用100%的问题
JFR定位由于可能的JDK11的bug导致Log4j2 CPU占用100%的问题
JFR定位由于可能的JDK11的bug导致Log4j2 CPU占用100%的问题
|
Dubbo Java Linux
Sentinel在docker中获取CPU利用率的一个BUG
微服务治理中限流、熔断、降级是一块非常重要的内容。目前市面上开源的组件也不是很多,简单场景可以使用Guava,复杂场景可以选用Hystrix、Sentinel。今天要说的就是Sentinel,Sentinel是一款阿里开源的产品,
441 0
Sentinel在docker中获取CPU利用率的一个BUG
|
调度
【高并发】为何在32位多核CPU上执行long型变量的写操作会出现诡异的Bug问题?看完这篇我懂了!
我们在32位多核CPU的计算机上以多线程的方式读写long类型的共享变量时,线程已经将变量成功写入了内存,但是重新读取出来的数据和之前写入的数据不一致,这到底是为什么呢?
326 0
【高并发】为何在32位多核CPU上执行long型变量的写操作会出现诡异的Bug问题?看完这篇我懂了!
|
Java 数据安全/隐私保护 测试技术
我修复的印象最深的一个bug,一个导致CPU和内存异常到无法响应的BUG
系统上线一段时间后,客户反映接口响应特别慢,甚至没有响应,第一时间依次检查了网络、服务器资源使用情况,发现服务器CPU和内存占用率都非常的高,经过一阵紧张的排查,最终发现问题出现的根源,这就是我修复的印象最深的一个bug就是由于String的用法不当所造成的。
482 0
我修复的印象最深的一个bug,一个导致CPU和内存异常到无法响应的BUG

热门文章

最新文章

相关实验场景

更多