I am trying to understand ReadWriteLock. [ This code will just work in your IDE. Copy & paste. Try to do this yourself ]
class ReadWrite {
private static final ReadWriteLock LOCK = new ReentrantReadWriteLock();
private static final Lock READ_LOCK = LOCK.readLock();
private static final Lock WRITE_LOCK = LOCK.writeLock();
private static final int[] ARR = new int[1];
int i = 0;
Integer read(){
Integer value = null;
try{
READ_LOCK.lock();
value = ARR[0];
}catch (Exception e){
e.printStackTrace();
}finally {
READ_LOCK.unlock();
}
return value;
}
void write(){
try{
WRITE_LOCK.lock();
ARR[0] = i++;
}catch (Exception e){
e.printStackTrace();
}finally {
WRITE_LOCK.unlock();
}
}
}
I was trying to do a performance test.
AtomicInteger atomicInteger = new AtomicInteger(0);
ReadWrite rw = new ReadWrite();
// read 10 millions times
Runnable r1 = () -> IntStream.rangeClosed(1, 10_000_000).forEach(i -> {
if(rw.read() > 0)
atomicInteger.incrementAndGet();
});
Runnable r2 = rw::write;
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
Thread[] threads = new Thread[10];
long before = System.currentTimeMillis();
scheduledExecutorService.scheduleAtFixedRate(r2, 1, 1, TimeUnit.MICROSECONDS);
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(r1);
threads[i].start();
}
for (int i = 0; i < 10; i++) {
threads[i].join();
}
System.out.println("Time Taken :: " + (System.currentTimeMillis() - before));
System.out.println("No fo reads :: " + atomicInteger.get());
Ran this test few times.
Case 1:
When i use READ_LOCK for reading it takes 12 seconds to complete. no of reads is 100000000.
Case 2:
When I use WRITE_LOCK for both reading & writing (READ_LOCK not used in this case), it the test takes only 2.5 seconds. no of reads is 100000000.
I was thinking having separate locks should improve performance.
What is going on here? What is the mistake I do?