In note #1, keyword "synchronized" is used to synchronize threads. Keyword "synchronized" is not the only way to synchronize threads in Java. Another way is to use methods wait and notify. When a thread A encounters a wait method, it sleeps (becomes disabled). Thread A stays in this state till another thread wakes it (thread A) using a notify method.
For example, a producer thread produces some items, and a consumer thread consumes these items. If there are no items, then the consumer waits (becomes disabled) till the producer notifies the consumer of the availability of items. Afterwards, the consumer becomes enabled and consumes the available items.
The following methods are available in class Object:
Read this tutorial at Sun (http://java.sun.com/docs/books/tutorial/essential/threads/waitAndNotify.html).
- notify(): Wakes up a single thread that is waiting on this object. A thread waits on an object by calling one of the wait methods: wait(), wait(long), and wait(long,int).
- notifyAll(): Wakes up all threads that are waiting on this object.
- wait(): Causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
- wait(long timeout): Causes current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.
- wait(long timeout, int nanos): Causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.
Example 1
Example 1 is available at ExBound.java:
class ExBound {
public static void main (String argv[]) {
new Counter();
}
}
// This class creates four threads, that share a common counter.
// Two threads repeat the following sequence for 25000 times:
// - Reads the counter value into a variable
temp.
// - Increments temp by 1.
// - Stores temp into counter.
//
// The other two threads repeat the following sequence for 25000
times:
// - Reads the counter value into a variable
temp.
// - Decrements temp by 1.
// - Stores temp into counter.
//
// There is an extra condition: "counter" stays within [0,100].
So, if
// a thread wants to increase "counter" while its value is 100,
the thread has to
// wait till the value of "counter" becomes less than 100. Similarly,
if a thread
// wants to decrement "counter" while its value is zero, the thread
has to wait
// till the value of "counter" becomes bigger than zero.
//
// After incrementing "counter" for 50000 and decrementing "counter"
50000,
// the value of the counter is zero.
//
class Counter {
Entity counter = new Entity();
Counter(){
IncThread th1 = new
IncThread("th1");
DecThread th2 = new
DecThread("th2");
IncThread th3 = new
IncThread("th3");
DecThread th4 = new
DecThread("th4");
th1.start();
th2.start();
th3.start();
th4.start();
System.out.println("Threads
running.");
}
class DecThread extends Thread {
String name;
DecThread(String name){
this.name = name;
}
public void run(){
for (int i=0; i < 25000; i++){
synchronized(counter){
try {
while (counter.counter <= 0)
counter.wait();
} catch (InterruptedException ie){
System.out.println("Monitor violated");
}
int temp = counter.counter;
yield();
temp = temp -1;
yield();
counter.counter = temp;
yield();
// Notify other threads that 0 < counter =< 100
if (counter.counter > 0)
counter.notifyAll();
if (counter.counter > 100 || counter.counter < 0)
throw new Error("Error: counter violates [0,100]");
}
}
System.out.println(name + " counter = " + counter.counter);
}
}
class IncThread extends Thread {
String name;
IncThread(String name){
this.name = name;
}
public void run(){
for (int i=0; i < 25000; i++){
synchronized(counter){
try {
while (counter.counter >= 100)
counter.wait();
} catch (InterruptedException ie){
System.out.println("Monitor violated");
}
int temp = counter.counter;
yield();
temp = temp + 1;
yield();
counter.counter = temp;
yield();
// Notify other threads that 0 =< counter < 100
if (counter.counter < 100)
counter.notifyAll();
if (counter.counter > 100 || counter.counter < 0)
throw new Error("Error: counter violates [0..100]");
}
}
System.out.println(name + " counter = " + counter.counter);
}
}
}
class Entity extends Object {
// Initialize counter to zero. What happens
if counter's value is outside
// [0..100]?
public int counter = 0;
}
This program is compiled using command "javac ExBound.java",
and
is executed using command "java ExBound".
Notes about example 1: