THE UNIVERSITY OF WESTERN AUSTRALIA
Department of Computer Science
230.304 CONCURRENT PROGRAMMING
Laboratory Sheet 3 (for laboratories during week 5)
The purpose of this laboratory is to :
- Learn how to synchronize the execution of multiple threads in a Java
program.
- Learn about other methods and declarations related to concurrency
support in Java, and
- Continue writing incorrect and correct attempts to solve the mutual
exclusion problem.
Synchronizing Threads
Till now, our threads have executed at their own will or, rather at the
will of the scheduler. However, as you have seen in the lectures, you may need
to coordinate the access of multiple threads to shared objects in your program.
Java allows you to coordinate the actions of multiple threads using
synchronized methods and synchronized statements.Here is how
it is done. You may not understand the following description completely, but
it will be clear when we discuss monitors in the lectures. You should
now follow the example program to understand the language features used in
synchronizing threads.
The synchronized methods are declared with the synchronized
keyword. Only one synchronized method can be invoked for an object at a
given point. This prevents synchronized methods from multiple objects from
conflicting with each other.
All classes and objects are associated with a unique monitor.
The monitor associated with an object is used to control the way in
which synchronized methods access the class or object. When a synchronized
method is invoked for an object, it is said to acquire
the monitor for that object.
No other synchronized method can be invoked for that object until the
monitor is released. A monitor is automatically realeased when the execution
of the method is complete or when the synchronized method executes a
method like wait(). In the second case, the thread associated
with the currently executing synchronized method becomes not runnable
until the wait condition is satisfied and no other method has acquired the
object's monitor.
Here is an example program for synchronizing
the execution of two threads. This is based on the Example1.java
program in lab1.
Here is some explanation of the program.
- The Example5 class is the same as the Example1
class.
- The MyThread class is modified to use the SynchronizedOutput
class. We use the method display in this class to display the
output instead of doing it in the run() method.
- It is important to note here that the display method is
static and applies to the SynchronizedOutput class as a whole and
not to an instance of this class.
- The main difference is the following. When display() is not
synchronized, it may be invoked by one thread which displays some output
and the other thread executes and so on. But now, thread1 invokes
display and acquires a monitor for the SynchronizedOutput
class and display() proceeds with the output of thread1. thread2
must wait until the monitor is released.
Java Concurrency Constructs
The following are the concurrency constructs and support in the Java
language. Though this list is quite small, it is possible to write
a wide range of concurrent programs with these constructs.
- The class java.lang.Thread used to initiate and control
new threads. You have already seen some examples.
- The keywords synchronized and volatile. You have
seen the use of the former in the example above. The volatile
keyword is used to declare variables which may be updated
asynchronously by multiple threads. Since we don't know the
order in which such variables will be modified, the volatile
keyword informs the compiler of the special nature of such a variable.
- The methods wait, notify and notifyAll
defined in java.lang.Object. These methods are used to
coordinate activities across threads.
Waiting and Notification
- The wait, notify and notifyAll methods are
used in programs in which activities in different threads are intended
to affect one another.
- Any synchronized method in any object can contain a wait which
suspends the current thread. As you have learnt earlier, a thread
can execute a synchronized method by acquiring a monitor
for the method. When a thread executes wait, it releases the
monitor for that synchronized method and other threads can now
acquire the monitor.
- All threads waiting on the target object (the monitor), are resumed
upon invocation of the notifyAll method. One arbitrarily chosen
thread is resumed upon invocation of the notify method.
- Here is an example program
Example6.java using wait
and notifyAll for synchronizing threads.
- In Java, both sleep and wait can be broken abnormally by
an InterruptedException and hence a wait call should
be enclosed in a try block.
- If several threads are trying to acquire a monitor object to
execute synchronized methods, the monitor puts all such
threads in a queue. A thread in the queue waits for the synchronized
method(s) to be free. A thread may also get queued if it has explicitly
called wait. However, such a thread can only wake up if it
is notified by a notify or notifyAll.
- Note: It is an error for a thread executing outside a monitor
(i.e., a synchronized method) to issue a wait, notify
or notifyAll. This causes an
IllegalMonitorStateException to be thrown.
Tasks
Amitava Datta
March, 2000