JAVA-BASED REAL-TIME PROGRAMMING
JAVA-BASED REAL-TIME PROGRAMMING
JAVA-BASED REAL-TIME PROGRAMMING
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
3.3. Objects providing mutual exclusion – Monitors<br />
withdraw method) but concurrent calls of withdraw can give the wrong<br />
result. This is because the withdraw method no longer is reentrant. For<br />
instance, one caller (with low priority) locks the resource and carries out<br />
the transaction, while a second thread (with high priority) preempts the<br />
first thread between lines 16 and 17. When resuming, the first thread<br />
will return the result of the second call and the result of the first transaction<br />
is lost, that is, if amount>balance.<br />
Making a method or function reentrant by only using local variables (allocated<br />
on the stack of each thread) is standard; we need to understand that no<br />
matter if we use a language supporting synchronized or not. However, with<br />
the availability of synchronized as in Java, we do not need to introduce the<br />
ans variable at all. Furthermore, returning from a method never results in the<br />
resource being left in its locked state; on return the Java compiler produces<br />
the executable code that unlocks the object.<br />
Basic use of keyword synchronized<br />
There are cases when synchronized blocks are appropriate, but in general we<br />
better follow a few simple rules:<br />
1. For each class, decide if an instance should be an ordinary object (not<br />
caring about concurrency), a thread object, or a monitor. Do not mix<br />
threads and monitors.<br />
2. Monitors should have all public methods synchronized (except the constructors)<br />
and no public attributes. Subclasses of monitors should also<br />
have to declare all methods synchronized since synchronized is not inherited.<br />
3. If you need to make an ordinary class thread safe, you could create a<br />
monitor by defining a subclass, but then you have to override all methods<br />
in order to declare them as synchronized. Methods that are final is a<br />
problem. Instead of subclassing, it is usually better to write a wrapper<br />
class being a monitor containing the ordinary object.<br />
4. Do not use synchronized blocks, which are contradictory to proper objectoriented<br />
design of concurrent software and to the monitor concept as<br />
such.<br />
The reason for rule A is that the actions of a thread is defined via a method<br />
(run) which from a purely object-oriented point of view is a method like any<br />
other, with access to all attributes of the object. Mutual exclusion between the<br />
internal thread (executing the run method) and the external threads (calling<br />
the monitor methods) would require the run method to be synchronized as<br />
well. Another alternative could be to only access the attributes of the object<br />
69