-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
6
-
Fix Understood
-
x86
-
windows_xp
FULL PRODUCT VERSION :
java version "1.6.0_05"
Java(TM) SE Runtime Environment (build 1.6.0_05-b13)
Java HotSpot(TM) Client VM (build 10.0-b19, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Windows XP ver 2002 SP 2
A DESCRIPTION OF THE PROBLEM :
In non-fair mode, a reader may wait even if the write lock is NOT actually held by any thread. The scenario is as follows:
1) Thread A acquires a read lock for a very long time
2) Thread B tries to acquire a write lock but blocks because of the reader
3) Thread C tries to acquire the read lock, but instead of running concurrently with thread A, it also blocks.
This behavior would be normal in the fair mode.
The documentation of ReentrantReadWriteLock.ReadLock.lock() states:
"Acquires the read lock if the write lock is not held by another thread and returns immediately."
If the observed behavior is correct, then the documentation must be updated. Furthermore, this behavior will result in low throughput for scenarios with slow readers.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Follow the three steps I mentioned (in non-fair mode):
1) Thread A acquires a read lock for a very long time
2) Thread B tries to acquire a write lock but blocks because of the reader
3) Thread C tries to acquire the read lock
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would expect thread C to acquire the read lock successfully.
ACTUAL -
Thread C waits because of a waiting writer (thread B).
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class TestRWL {
private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);
public static void main(String[] args) throws InterruptedException {
//A reader which takes too long to finish
new Thread(){
public void run(){
lock.readLock().lock();
try{
try {
Thread.sleep(1000*60*60);
} catch (InterruptedException e) {
}
}finally{
lock.readLock().unlock();
}
}
}.start();
Thread.sleep(3000);
//A writer which will be waiting
new Thread(){
public void run(){
lock.writeLock().lock();
lock.writeLock().unlock();
}
}.start();
Thread.sleep(3000);
//Another reader
new Thread(){
public void run(){
System.out.println("Trying to acquire a second read lock...");
lock.readLock().lock();
try{
System.out.println("Second read lock acquired successfully!!");
}finally{
lock.readLock().unlock();
}
}
}.start();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
It looks like ReentrantReadWriteLock.readLock().tryLock() DOES acquire the lock...
java version "1.6.0_05"
Java(TM) SE Runtime Environment (build 1.6.0_05-b13)
Java HotSpot(TM) Client VM (build 10.0-b19, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Windows XP ver 2002 SP 2
A DESCRIPTION OF THE PROBLEM :
In non-fair mode, a reader may wait even if the write lock is NOT actually held by any thread. The scenario is as follows:
1) Thread A acquires a read lock for a very long time
2) Thread B tries to acquire a write lock but blocks because of the reader
3) Thread C tries to acquire the read lock, but instead of running concurrently with thread A, it also blocks.
This behavior would be normal in the fair mode.
The documentation of ReentrantReadWriteLock.ReadLock.lock() states:
"Acquires the read lock if the write lock is not held by another thread and returns immediately."
If the observed behavior is correct, then the documentation must be updated. Furthermore, this behavior will result in low throughput for scenarios with slow readers.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Follow the three steps I mentioned (in non-fair mode):
1) Thread A acquires a read lock for a very long time
2) Thread B tries to acquire a write lock but blocks because of the reader
3) Thread C tries to acquire the read lock
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would expect thread C to acquire the read lock successfully.
ACTUAL -
Thread C waits because of a waiting writer (thread B).
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class TestRWL {
private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);
public static void main(String[] args) throws InterruptedException {
//A reader which takes too long to finish
new Thread(){
public void run(){
lock.readLock().lock();
try{
try {
Thread.sleep(1000*60*60);
} catch (InterruptedException e) {
}
}finally{
lock.readLock().unlock();
}
}
}.start();
Thread.sleep(3000);
//A writer which will be waiting
new Thread(){
public void run(){
lock.writeLock().lock();
lock.writeLock().unlock();
}
}.start();
Thread.sleep(3000);
//Another reader
new Thread(){
public void run(){
System.out.println("Trying to acquire a second read lock...");
lock.readLock().lock();
try{
System.out.println("Second read lock acquired successfully!!");
}finally{
lock.readLock().unlock();
}
}
}.start();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
It looks like ReentrantReadWriteLock.readLock().tryLock() DOES acquire the lock...
- links to
-
Review(master) openjdk/jdk/25880