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     for( int 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 }
目录
相关文章
|
并行计算 安全 Java
深入理解Java并发编程:并行与并发、进程与线程、优先级、休眠与让步
深入理解Java并发编程:并行与并发、进程与线程、优先级、休眠与让步
316 0
|
缓存 算法 安全
Linux设备驱动程序(五)——并发和竞态 2
Linux设备驱动程序(五)——并发和竞态
35 0
|
Linux
Linux设备驱动程序(五)——并发和竞态 1
Linux设备驱动程序(五)——并发和竞态
39 0
|
缓存 Java 大数据
深入解析JVM调优:解决OutOfMemoryError、内存泄露、线程死锁、锁争用和高CPU消耗问题
深入解析JVM调优:解决OutOfMemoryError、内存泄露、线程死锁、锁争用和高CPU消耗问题
202 0
|
运维 Java
因死循环导致CPU飙升到100%的问题排查记录
因死循环导致CPU飙升到100%的问题排查记录
255 0
|
存储 安全 算法
《我要进大厂》- Java并发 夺命连环10问,你能坚持到第几问?(进程&线程 | 并行&并发 | 上下文切换 | 线程死锁 | 线程创建)
《我要进大厂》- Java并发 夺命连环10问,你能坚持到第几问?(进程&线程 | 并行&并发 | 上下文切换 | 线程死锁 | 线程创建)
《我要进大厂》- Java并发 夺命连环10问,你能坚持到第几问?(进程&线程 | 并行&并发 | 上下文切换 | 线程死锁 | 线程创建)
|
缓存 Java
一例JAVA多线程访问卡死的现象
一例JAVA多线程访问卡死的现象
164 0
|
Java
一个线程中断的Bug:明明中断了线程,却为何不起作用呢?
一个线程中断的Bug:当我们在调用Java对象的wait()方法或者线程的sleep()方法时,需要捕获并处理InterruptedException异常。如果我们对InterruptedException异常处理不当,则会发生我们意想不到的后果!今天,我们就以一个案例的形式,来为大家详细介绍下为何中断执行的线程不起作用。
415 0
一个线程中断的Bug:明明中断了线程,却为何不起作用呢?
线程中sleep导致崩溃是一种错觉
线程中sleep导致崩溃是一种错觉
178 0