Many times we come across a problem, when in the multithreaded environment some shared object has frequent read operations and write operations are rare. If we could use a concurrent collection that would be the best option in most of the cases, but sometimes we can't.
Let's imagine a situation when this shared object is in a 3rd party library. In our example this object is a Book class that I used in previous posts.
Most of the time we want to show information about the book, but exceptionally the author modifies the content and therefore the number of pages needs to be changed.
Using synchronized for the methods that read/write the book would be a poor solution.
Instead, we could use ReadWriteLock which allows to differentiate between read and write operations. Read operation is concurrent, which means that all the threads have access to the object. Only write operation is exclusive and blocks other threads.
Everything we do after acquiring the lock must be put in a try block, so that unlocking is done even if the exception is thrown.
Let's see it in action:
We have 10 threads that are performing 100 tasks. Only 10% of them are write tasks. When we run it, we can see that read operations are concurrent (lines about the reading thread and book info are mixed from time to time) and write operations are exclusive (info about writing thread and successful update are always in the correct order).
The example with the book is purely educational and not too realistic. In real life we would probably have some kind of a large collection. It's good to read ReentrantReadWriteLock and ReadWriteLock javadoc, because sometimes using them may bring more overhead than mutual exclusion.