Home  >  Core Java

Example of ReadWriteLock and ReentrantReadWriteLock in Java

By Arvind Rai, December 17, 2012
This page will provide example of ReadWriteLock and ReentrantReadWriteLock in java. ReadWriteLock and ReentrantReadWriteLock both have been introduced in JDK 1.5. ReentrantReadWriteLock is the implementation of ReadWriteLock interface and ReadWriteLock extends Lock interface. ReentrantReadWriteLock is the implementation of ReadWriteLock with reentrancy. ReentrantReadWriteLock has associated read and write lock that can reacquire the locks. Here on this page we will discuss ReadWriteLock and ReentrantReadWriteLock with complete example.

Lock

java.util.concurrent.locks.Lock interface has been introduced in JDK 1.5. Lock can replace the use of synchronized methods and will facilitate more effective locking system. Lock is used in multithreaded environment for shared resources. Lock plays its game in the way that any thread must have to get lock first to access a shared resources protected by Lock. Only one thread can acquire a lock at a time, once its job is complete, it unlocks the resource for other threads in queue. ReadWriteLock is an interface which extends Lock.

ReadWriteLock

java.util.concurrent.locks.ReadWriteLock interface has been introduced in JDK 1.5. ReadWriteLock is the pair of associated lock for read and write operation. The request for read lock by multiple threads can be acquired simultaneously if there is no write lock request. If a thread acquires write lock on a resource, then no other read or writes lock by any thread can be acquired for that resource. ReadWriteLock is more effective in the scenario where read operation is more frequent than write operation because read lock can be acquired by multiple threads at the same time for a shared resource.

ReentrantReadWriteLock

java.util.concurrent.locks.ReentrantReadWriteLock class has been introduced in JDK 1.5. ReentrantReadWriteLock is the implementation of ReadWriteLock. We will discuss some main properties of ReentrantReadWriteLock as follows.

Acquisition order
ReentrantReadWriteLock can behave as fair and non-fair mode both. The default behavior is non-fair. The performance of non-fair lock is better though it is possible that a reader or writer lock can be postponed many times which are continuously trying to lock. In case of fair lock the locking request is fulfilled in the order that either the longest waiting single writer lock or the group of read locks request, whosoever has longest waiting time will acquire lock on the shared resource.

Reentrancy
ReentrantReadWriteLock provides reentrancy for both read and write lock. It means read and write lock both can be reacquired.

Lock downgrading
The reentrancy in ReentrantReadWriteLock can be downgraded from write lock to read lock. It means if a thread has acquired write lock, it can downgrade its lock from write to read lock. The sequence will be that first acquire write lock, do the write operation and then acquire read lock and then unlock the write lock and after read operation finally unlock the read lock.

Find the two main methods of ReentrantReadWriteLock.
readLock() : It requests for read operation lock.
writeLock() : It requests for write operation lock.

Complete Example of ReentrantReadWriteLock

For ReentrantReadWriteLock demo, we are creating a ScoreBoard class which provides two methods, one for update the flag for score update and second for getting score health that can be good or bad. Many threads will call these methods simultaneously and ReentrantReadWriteLock will handle the concurrency.
ScoreBoard.java
package com.concretepage.concurrent;
import java.util.Calendar;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ScoreBoard {
	private boolean scoreUpdated = false;
	private int score = 0;
        String health = "Not Available";
	final ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock();
	public String getMatchHealth() {
	    rrwl.readLock().lock();
	    if (scoreUpdated) {
	        rrwl.readLock().unlock();
	        rrwl.writeLock().lock();
	        try {
	          if (scoreUpdated) {
	        	  score = fetchScore();
	        	  scoreUpdated = false;
	          }
	          rrwl.readLock().lock();
	        } finally {
	          rrwl.writeLock().unlock(); 
	        }	
	    }   
	    try {
		     if (score % 2 == 0 ){
		          health = "Bad Score";
		      } else {
		    	  health = "Good Score";
		      }
	    } finally {
		      rrwl.readLock().unlock();
            }
	    return health;
	}
	public void updateScore() {
		try {
			rrwl.writeLock().lock();
			//perform more task here
			scoreUpdated = true;
		}finally {
			rrwl.writeLock().unlock();
		}
	}
	private int fetchScore() {
		Calendar calender = Calendar.getInstance();
		return calender.get(Calendar.MILLISECOND);
	}
} 
ScoreHealthThread.java
package com.concretepage.concurrent;
public class ScoreHealthThread implements Runnable {
	private ScoreBoard scoreBoard;
	public ScoreHealthThread(ScoreBoard scoreTable) {
		this.scoreBoard = scoreTable;
	}
	@Override
	public void run() {
		for(int i= 0; i< 5; i++) {
			System.out.println("Match Health: "+ scoreBoard.getMatchHealth());
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}		
	}
} 
ScoreUpdateThread.java
package com.concretepage.concurrent;
public class ScoreUpdateThread implements Runnable {
	private ScoreBoard scoreBoard;
	public ScoreUpdateThread(ScoreBoard scoreTable) {
		this.scoreBoard = scoreTable;
	}
	@Override
	public void run() {
		for(int i= 0; i < 5; i++) {
			System.out.println("Score Updated.");		
			scoreBoard.updateScore();
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
} 
Main.java
package com.concretepage.concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
	public static void main(String[] args) {
		final int threadCount = 2;
		final ExecutorService exService = Executors.newFixedThreadPool(threadCount);
		final ScoreBoard scoreBoard = new ScoreBoard();
		exService.execute(new ScoreUpdateThread(scoreBoard));
		exService.execute(new ScoreHealthThread(scoreBoard));			
		exService.shutdown();
	}
} 
Find the output.
Score Updated.
Match Health: Good Score
Score Updated.
Match Health: Bad Score
Score Updated.
Match Health: Good Score
Score Updated.
Match Health: Bad Score
Score Updated.
Match Health: Good Score 


Now I am done. Happy java learning!

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
FIND MORE TUTORILAS






©2019 concretepage.com | Privacy Policy | Contact Us