StampedLock内部实现时,使用类似于CAS操作的死循环反复尝试的策略。在它挂起线程时,使用的是Unsafe.park()函数,而park()函数在遇到线程中断时,会直接返回(注意,不同于Thread.sleep()方法,他不会抛出异常)。而在StampedLock的死循环逻辑中,没有处理有关中断的逻辑。因此,这就会导致阻塞在park()方法上的线程被中断后,再次进入循环。而当退出条件得不到满足时,就会发生疯狂占用CPU的情况。演示代码如下:
package com.aden.powoms.biz.drgcompute.compute.biz.impl;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.StampedLock;
/**
* StampedLock 的小陷阱Demo
*/
public class StampedLockCPUDemo {
private static Thread[] holdCpuThreads = new Thread[3];
private static StampedLock lock = new StampedLock();
public static void main(String[] args) throws InterruptedException {
new Thread(){
@Override
public void run() {
long readLong = lock.writeLock();
LockSupport.parkNanos(600000000000L);
lock.unlockWrite(readLong);
}
}.start();
Thread.sleep(1000);
// 线程中断后,会占用CPU
for(int i = 0; i < 3; ++ i){
holdCpuThreads[i] = new Thread(new HoldCPUReadThread());
holdCpuThreads[i].start();
}
}
private static class HoldCPUReadThread implements Runnable {
@Override
public void run() {
long locker = lock.readLock();
System.out.println(Thread.currentThread().getName() + " 获得读锁");
lock.unlockRead(locker);
}
}
}
版权声明:本文为jay_888原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。