I have created 1000 threads to increment,1000 threads to decrement,1000 threads to read the value.
Each increment thread ,increases value by 25000 times.
Each decrement thread ,decreases value by 25000 times.
Each read thread ,reads the value by 50000 times.
so over all the operation is Read dominant.
The ReadLock is put while reading the value
and WriteLock is put for methods incrementing & decrementing the values.
Observed: ReentrantReadWriteLock takes around 13000 ms Lock takes around 3000 ms. Expected : ReentrantReadWriteLock to give much faster performance than ReentrantLock.
BTW: I personally think there is no need to have lock/synchronization while using getCounter method ( just reading the value )
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Main {
public static void main(String[] args) throws InterruptedException {
ArrayList<Thread> reads = new ArrayList<>();
ArrayList<Thread> increments = new ArrayList<>();
ArrayList<Thread> decrements = new ArrayList<>();
Resources resources = new Resources();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
Thread read = new Read(resources);
Thread increment = new Increment(resources);
Thread decrement = new Decrement(resources);
reads.add(read);
increments.add(increment);
decrements.add(decrement);
read.start();
increment.start();
decrement.start();
}
for (int i = 0; i < 1000; i++) {
reads.get(i).join();
increments.get(i).join();
decrements.get(i).join();
}
System.out.println(resources.getCounter());
System.out.println(System.currentTimeMillis() - start);
}
private static abstract class UserThread extends Thread {
protected Resources resources;
public UserThread(Resources resources) {
this.resources = resources;
}
}
private static class Read extends UserThread {
public Read(Resources resources) {
super(resources);
}
public void run() {
for (int i = 0; i < 50000; i++) {
resources.getCounter();
}
}
}
private static class Increment extends UserThread {
public Increment(Resources resources) {
super(resources);
}
public void run() {
for (int i = 0; i < 25000; i++) {
resources.increment();
}
}
}
private static class Decrement extends UserThread {
public Decrement(Resources resources) {
super(resources);
}
public void run() {
for (int i = 0; i < 25000; i++) {
resources.decrement();
}
}
}
private static class Resources {
private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
private ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
private ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
private ReentrantLock lock = new ReentrantLock();
public int getCounter() {
readLock.lock();
try {
return counter;
} finally {
readLock.unlock();
}
}
private int counter = 0;
public void increment() {
writeLock.lock();
try {
counter++;
} finally {
writeLock.unlock();
}
}
public void decrement() {
writeLock.lock();
try {
counter--;
} finally {
writeLock.unlock();
}
}
}
}