Note # 2

Notes about wait and notify


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).

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: