FULL PRODUCT VERSION :
java version "1.8.0_05"
java<TM> SE Runtime Environment <build 1.8.0_05-b13>
Java HotSpot<TM> Client VM <build 25.5-b02, mixed mode, sharing>
A DESCRIPTION OF THE PROBLEM :
When we call the readLock method of StampedLock������If the thread is already in the interrupt status������so even before obtaining the lock, the thread will always spin, which filled the CPU:
public class BugOfInterruptedThread {
public static void main(String[] args) throws InterruptedException{
final StampedLock lock = new StampedLock();
new Thread(){
public void run(){
long readLong = lock.writeLock();
LockSupport.parkNanos(6100000000L);
lock.unlockWrite(readLong);
}
}.start();
Thread.sleep(100);
for( int i = 0; i < 3; ++i)
new Thread(new OccupiedCPUReadThread(lock)).start();
}
private static class OccupiedCPUReadThread implements Runnable{
private StampedLock lock;
public OccupiedCPUReadThread(StampedLock lock){
this.lock = lock;
}
public void run(){
Thread.currentThread().interrupt();
long lockr = lock.readLock();
System.out.println(Thread.currentThread().getName() + " get read lock");
lock.unlockRead(lockr);
}
}
}
Execute the above code, three cores are filled in six seconds of time.
The reason is that when readLock method detects the interrupt is not cleared and saved (and later restored) interrupt.
REGRESSION. Last worked in version 8u5
ADDITIONAL REGRESSION INFORMATION:
java version "1.8.0_05"
java<TM> SE Runtime Environment <build 1.8.0_05-b13>
Java HotSpot<TM> Client VM <build 25.5-b02, mixed mode, sharing>
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Perform the following code, observe CPU usage������
public class BugOfInterruptedThread {
public static void main(String[] args) throws InterruptedException{
final StampedLock lock = new StampedLock();
new Thread(){
public void run(){
long readLong = lock.writeLock();
LockSupport.parkNanos(6100000000L);
lock.unlockWrite(readLong);
}
}.start();
Thread.sleep(100);
for( int i = 0; i < 3; ++i)
new Thread(new OccupiedCPUReadThread(lock)).start();
}
private static class OccupiedCPUReadThread implements Runnable{
private StampedLock lock;
public OccupiedCPUReadThread(StampedLock lock){
this.lock = lock;
}
public void run(){
Thread.currentThread().interrupt();
long lockr = lock.readLock();
System.out.println(Thread.currentThread().getName() + " get read lock");
lock.unlockRead(lockr);
}
}
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Before acquiring the lock, the thread hangs.
ACTUAL -
Before acquiring the lock, the thread always occupy CPU.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class BugOfInterruptedThread {
public static void main(String[] args) throws InterruptedException{
final StampedLock lock = new StampedLock();
new Thread(){
public void run(){
long readLong = lock.writeLock();
LockSupport.parkNanos(6100000000L);
lock.unlockWrite(readLong);
}
}.start();
Thread.sleep(100);
for( int i = 0; i < 3; ++i)
new Thread(new OccupiedCPUReadThread(lock)).start();
}
private static class OccupiedCPUReadThread implements Runnable{
private StampedLock lock;
public OccupiedCPUReadThread(StampedLock lock){
this.lock = lock;
}
public void run(){
Thread.currentThread().interrupt();
long lockr = lock.readLock();
System.out.println(Thread.currentThread().getName() + " get read lock");
lock.unlockRead(lockr);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Instead of using ReentrantReadWriteLock.