I had a chance to work on multi-threading in Java when I was working with Siemens in 2001 where I was part of a product development for Power Plant Automation System. I extensively used multi-threading using synchronization, wait, notify etc.
After a long time, I was going through the new developments in Java Concurrency and I really liked those features. Here is an example for usage of ReadWtiteLock in Java Concurrency.
Let me first make one thing clear: Many people might get an obvious question that why do we need read lock when reading any Resource by multiple threads can be always safe. How ever, think about a situation where a shared Resource is under modification and the same Resource is being read by another thread. Probably, it might be a good idea to stop that as the kind of modification is not known and hence the state of the Resource might be not in a good state to read either. If we want to achieve this without using Java Concurrency util Locks, I can't think of any simple mechanism to achieve this without using 'synchronize' the read and write blocks of the Resource on the same object. Using 'synchronize' on the read and write blocks would functionally work but that has a flip side. That would not allow multiple threads to read even if there is no write is taking place, which is too much to stop.
java.util.concurrency.lock,ReadWriteLock will solve the above issue. I would like to explain this with an example:
Resource.java
-----------------------------------------------------------------------------------------
public class Resource {
public Resource() {
super();
}
public void read() throws Exception{
System.out.println("Thread: " + Thread.currentThread().getName() +" executing Read...");
Thread.sleep(5000);
System.out.println("Thread: " + Thread.currentThread().getName() +" exit Read");
}
public void write() throws Exception{
System.out.println("Thread: " + Thread.currentThread().getName() +" executing Write...");
Thread.sleep(5000);
System.out.println("Thread: " + Thread.currentThread().getName() +" exit Write");
}
}
---------------------------------------------------------------------------------------------
ReadThread.java
---------------------------------------------------------------------------------------------
public class ReadThread extends Thread {
Resource r = null;
ReadWriteLock lock = null;
public ReadThread(String name, Resource r, ReadWriteLock lock) {
super(name);
this.r = r;
this.lock = lock;
}
public void run(){
//lock.readLock().lock();
try{
r.read();
}
catch(Exception e){
e.printStackTrace();
}
/*finally{
lock.readLock().unlock();
}*/
}
}
--------------------------------------------------------------------------------------------------
WriteThread.java
--------------------------------------------------------------------------------------------------
import java.util.concurrent.locks.ReadWriteLock;
public class WriteThread extends Thread{
Resource r = null;
ReadWriteLock lock = null;
public WriteThread(String name, Resource r, ReadWriteLock lock) {
super(name);
this.r = r;
this.lock = lock;
}
public void run(){
//lock.writeLock().lock();
try{
r.write();
}catch(Exception e){
e.printStackTrace();
}
/*finally{
lock.writeLock().unlock();
}*/
}
}
---------------------------------------------------------------------------------------------------
ThreadTest.java
---------------------------------------------------------------------------------------------------
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ThreadTest {
public ThreadTest() {
super();
}
public static void main(String[] args){
Resource r = new Resource();
ReadWriteLock lock = new ReentrantReadWriteLock();
Thread t1 = new ReadThread("R1", r, lock);
Thread t2= new WriteThread("W1", r, lock);
Thread t3 = new ReadThread("R2",r, lock);
t2.start();
t1.start();
t3.start();
}
}
--------------------------------------------------------------------------------------------------
If you run the above program output would be some like this:
Thread: W1 executing Write...
Thread: R2 executing Read...
Thread: R1 executing Read...
Thread: R2 exit Read
Thread: R1 exit Read
Thread: W1 exit Write
This is obvious as the program does not use any kind of synchronize or lock and multiple threads are able to read and write the resource in parallel. Please note that, the code has ReadWriteLock but the lock is not used in the actual Threads (ReadThread and WriteThread). You might get different output based on which thread gets actually run.
Now, let me change the code to use ReadWriteLock:
ReadThread.java
----------------------------------------------------------------------------------------------------
import java.util.concurrent.locks.ReadWriteLock;
public class ReadThread extends Thread {
Resource r = null;
ReadWriteLock lock = null;
public ReadThread(String name, Resource r, ReadWriteLock lock) {
super(name);
this.r = r;
this.lock = lock;
}
public void run(){
lock.readLock().lock();
try{
r.read();
}
catch(Exception e){
e.printStackTrace();
}
finally{
lock.readLock().unlock();
}
}
}
-----------------------------------------------------------------------------------------------------
WriteThread.java
-----------------------------------------------------------------------------------------------------
import java.util.concurrent.locks.ReadWriteLock;
public class WriteThread extends Thread{
Resource r = null;
ReadWriteLock lock = null;
public WriteThread(String name, Resource r, ReadWriteLock lock) {
super(name);
this.r = r;
this.lock = lock;
}
public void run(){
lock.writeLock().lock();
try{
r.write();
}catch(Exception e){
e.printStackTrace();
}
finally{
lock.writeLock().unlock();
}
}
}
-----------------------------------------------------------------------------------------------------
No change in the TestThread.java (main program). By running the TestThread again with the above code for ReadThread and WriteThread, I have got the following output:
Thread: W1 executing Write...
Thread: W1 exit Write
Thread: R1 executing Read...
Thread: R2 executing Read...
Thread: R1 exit Read
Thread: R2 exit Read
If you notice keenly, Reader threads are not allowed to read while Writer thread was writing on the Resource.
Please note that, you might get different output based on which thread gets to run, but one thing will be always true. Once the Write thread is writing, no Reader thread will be allowed.
Hopefully, this would be useful...