Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Lock on to an alternate synchronization mechanism

Learn how to implement a reader/writer lock for flexible protection

  • Print
  • Feedback
Software professionals have been debating multithreaded programming for quite some time now. The notion of threading is so ingrained within the Java platform that developers can rarely create even simple programs without inadvertently using threads. Although the built-in threading support within the Java platform has allowed developers to create powerful programs, it has also left its share of scarred developers. The most common hazards lie in event-handling and the access of AWT/JFC Swing components. Rudimentary as it is, Java's built-in thread support is powerful enough to help build the most complex synchronization mechanisms required for commercial applications. The aim of this article is to illustrate that power by creating a reader/writer lock. The reader/writer lock implementation discussed here includes lock upgrade and downgrade capabilities. I'll also examine enhancements such as lock-leasing, various performance improvement tips, and ways of dealing with issues such as priority inversion.

The reader/writer lock

I would like to clear up the fair amount of misconception that remains about the reader/writer lock. The name implies the presence of two distinct locks -- one for reading and one for writing. However, that is not the case. A reader/writer lock is a single lock. Think of it as a lock with two levels, much like a building with two floors or a game with two levels -- beginner and advanced.

A reader/writer lock can be acquired simultaneously by multiple threads as long as the threads only read from the shared resource that the lock is protecting. If the thread wants to write or modify the shared resource, only one thread at a time can acquire the lock.

That lock is useful if the read operation is lengthy, and no reason presents itself in preventing other threads from reading the shared resource at the same time -- reading a file, reading the value of a static class variable, or reading a row from a table in a database, as examples. However, to ensure data integrity, only one thread can modify the shared resource. While it is making changes, no other threads are allowed access to the resource, even to read it. Thus, no other thread sees any intermediate changes or values of the shared resource.

Consider a list of all the names of people who have ever lived on the face of the earth as an example. The list is singly-linked, meaning traversal is possible in only one direction. Since it is a list, no random access is allowed. The list of names is huge -- several billion people long, at least. Searching for a particular individual in such a list is time-consuming in itself. Now imagine a million clients accessing the list continuously, each one either looking for an individual, or inserting a newly born person in the list, or both. The simplest multithreaded program would synchronize on the list during the search and insert operations. But that means that we have serialized all access to the list, thereby foregoing almost all benefits bestowed upon us by Java's multithreaded capability.

  • Print
  • Feedback

Resources
  • Source code
  • Books