ReadWriteLock provides similar functionality as ReentrantLock. You can create read lock and write lock  from ReadWriteLock. Read lock does not block other threads allowing read operations. Write lock blocks other threads that are either trying to read or write.

General behavior is as follows:

A ReadWriteLock is initialized to guard a shared resource. The readLock method returns a new Lock for read operations. The writeLock method returns a new Lock for write operations. So there are 3 lock objects where ReadWriteLock is just used for the creation of other 2 locks. Read operations can be performed in parallel. But write operations are performed serially.

Let’s say, we have a dictionary object that allows putting and getting key-value pairs. Read operations can be performed in parallel by multiple threads. But once a write operation is being performed, no other read and write operation should be allowed.

public class ReadWriteLockTest {

    public static void main(String[] args) throws InterruptedException {
        readWriteLock();
    }

    public static void readWriteLock() throws InterruptedException {
        final RWDictionary dictionary = new RWDictionary();
        final AtomicInteger index = new AtomicInteger();
        final ExecutorService threadPool = Executors.newFixedThreadPool(10);
        class Putter implements Runnable {

            @Override
            public void run() {
                dictionary.put(String.valueOf(index.getAndIncrement()), Thread.currentThread().getName());
            }
        }

        class Getter implements Runnable {

            @Override
            public void run() {
                dictionary.get(String.valueOf(index.get() - 1));
            }
        }

        threadPool.execute(new Getter());
        threadPool.execute(new Getter());
        threadPool.execute(new Putter());
        threadPool.execute(new Putter());
        threadPool.execute(new Getter());
        threadPool.execute(new Getter());
        threadPool.shutdown();
        threadPool.awaitTermination(10, TimeUnit.SECONDS);
    }

    /**
     * Taken from javadoc of ReentrantReadWriteLock
     */
    private static class RWDictionary {

        private final Map<String, Object> map = new TreeMap<>();
        private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        private final Lock readLock = readWriteLock.readLock();
        private final Lock writeLock = readWriteLock.writeLock();

        public Object get(String key) {
            System.out.println("Attempting to acquire read lock");
            readLock.lock();
            System.out.println("Acquired read lock");
            try {
                return map.get(key);
            } finally {
                readLock.unlock();
            }
        }

        public String[] allKeys() {
            readLock.lock();
            try {
                return map.keySet().toArray(new String[0]);
            } finally {
                readLock.unlock();
            }
        }

        public Object put(String key, Object value) {
            System.out.println("Attempting to acquire write lock");
            writeLock.lock();
            System.out.println("Acquired write lock");
            try {
                sleep(100);
                return map.put(key, value);
            } finally {
                writeLock.unlock();
            }
        }

        public void clear() {
            writeLock.lock();
            try {
                map.clear();
            } finally {
                writeLock.unlock();
            }
        }
    }
}

 

 

 

Leave a Reply

Close Menu