|
|
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
Multithreaded programming is challenging but unavoidable, which is why you need the best tools and techniques for doing it safely. In this article Theodore S. Norvell introduces the conceptual underpinnings of Hoare-style monitors (such as the use of exclusive access, conditions, and assertions) then presents his own Java-based monitor package that automates assertion checking during execution.
It is all too easy to write unsafe multithreaded Java code, in part because the language's notify() and wait() methods can be difficult to use correctly. In 1974, Tony Hoare proposed the concept of monitors for designing and reasoning about objects that are shared between multiple threads. The key property of these "Hoare-style"
monitors is that threads can wait until some specific assertion about the monitor's state is true and be guaranteed that it
is still true after the thread has been awakened.
In this article, I describe an open source Java class library that supports the monitor concept much as Hoare originally proposed it. As I will demonstrate, object-oriented technology makes it possible to improve on Hoare's concept by making assertions -- which are traditionally stated as comments and then repeated in if statements and assert statements -- executable objects. This approach reduces redundant coding and automates assertions checking during execution.
I'll start by explaining why multithreaded programming is as unavoidable as it is challenging, then introduce you to the use of exclusive access, conditions and assertions in Hoare-style monitors. See the Resources section to download the Java-based monitors package.
Three factors contribute to the ubiquity of multithreaded software, and thus the need for monitors:
Coordinating the activities of two or more threads can be very tricky and can be a source of latent defects in multithreaded code. Testing is ineffective because tests may not reveal race conditions. As software engineers we must equip ourselves with the intellectual and software tools to design correct multithreaded applications.
In the 1970s Edsger Dijkstra, Per Brinch Hansen and C.A.R. Hoare developed the idea of the monitor: an object that would protect data by enforcing single-threaded access. Only one thread at a time would be allowed to execute code within the monitor, making monitors islands of single-threaded calm in a turbulent sea of multithreadedness. Confining thread interactions to monitors would greatly improve the chance that they wouldn't interfere with each other in unanticipated ways.
A number of variants on the idea of monitors have been proposed and implemented in various programming languages such as Concurrent Pascal, Mesa, Concurrent Euclid, Turing and more recently Java. The idea of single-threaded access to a monitor is straightforward and the same in all these variants; where they differ is in how threads wait for the state of the monitor to change, and how they communicate to each other that the state has changed. Of all the these approaches, I've always found Hoare's version the easiest to use. In Hoare's version, occupancy of the monitor is transferred directly from a signaling to a signaled thread: the state of the monitor object cannot change between the signaling thread leaving and the signaled thread arriving.
For the rest of this article I'll focus on a Java package I've developed that implements Hoare-style monitors. In addition
to being a straightforward Java-based implementation of Hoare's original concept, the monitor package has one novel feature: it allows all assertions used in designing a monitor to be expressed as part of the code and
checked at runtime.
To get started, Table 1 summarizes the classes in the monitor package. See the Resources section for the source code for the monitor package.
public abstract class AbstractMonitor |
Abstract base class for monitor |
protected AbstractMonitor() |
Constructor |
protected boolean invariant() |
Hook method for invariant |
protected void enter() |
Obtain occupancy |
protected void leave() |
Relinquish occupancy |
protected Condition makeCondition( Assertion p ) |
Make a condition object |
protected Condition makeCondition() |
Make a condition with an always true assertion |
public class Monitor |
Monitor objects for delegation. |
public Monitor(Assertion invariant) |
Construct a monitor with a given invariant |
public void enter() |
Obtain occupancy |
public void leave() |
Relinquish occupancy |
public Condition makeCondition( Assertion p ) |
Make a condition object |
public Condition makeCondition() |
Make a condition with an always true assertion |
public class Condition |
Condition objects |
public void await() |
Wait for an assertion Pc to become true |
public void conditionalAwait() |
If Pc is not true, wait until it is |
public void signal() |
Signal that Pc is true |
public void conditionalSignal() |
If Pc is true, signal so |
public void signalAndLeave() |
Signal that Pc is true and leave the monitor |
public void conditionalSignalAndLeave() |
If Pc is true, signal so and leave the monitor |
public int count() |
The number of threads waiting |
public boolean isEmpty() |
Is the number of threads waiting 0? |
public abstract class Assertion |
Executable assertion objects |
public abstract boolean isTrue() |
Hook method |
Archived Discussions (Read only)