Java Tutorial

Synchronization

It is the process of allowing only one thread at a time among 'n' number of threads into that area which is sharable to perform write operation.

If anything (either data members or methods or objects or classes) is sharable then we must apply the concept of synchronization.

Let us assume that there is a sharable variable called balance whose initial value is zero. There are two threads t1 and t2 respectively. t1 and t2 want to update the balance variable with their respective values i.e., 10 and 20 at the same time. After completion of these two threads the final value in the balance is either 10 or 20 but not 30 which is the inconsistent result. To achieve the consistent result we must apply the concept of synchronization.

When we apply synchronization concept on the above scenario, when two threads are started at same time, the first thread which is started is given a chance to update balance variable with its respective value. When second thread is trying to access the balance variable value JVM makes the second thread to wait until first thread completes its execution by locking balance variable value. After completion of first thread the value in the balance is 10 and second thread will be allowed to update balance variable value. After completion of second thread the value of the balance is 30, which is the consistent result. Hence, in synchronization locking and unlocking is taking place until all the threads are completed their execution.

Synchronization Techniques:

In JAVA we have two types of synchronization techniques. They are synchronized methods and synchronized blocks.

1. Synchronized methods:

If any method is sharable for 'n' number of threads then make the method as synchronized by using a keyword synchronized.

In JAVA we have two types of synchronized methods. They are synchronized Instance methods and synchronized static methods.

Synchronized Instance methods: If the ordinary instance method is made it as synchronized then the object of the corresponding class will be locked.

Syntax:

synchronized <return type> method name (method parameters if any)
{
    Block of statements;
}

For example:

class Account {

    int bal = 0;

    synchronized void deposit(int amt) {
        bal = bal + amt;
        System.out.println("CURRENT BALANCE =" + bal);
    }
};

Synchronized static method: If an ordinary static method is made it as synchronized then the corresponding class will be locked.

Syntax:

synchronized static <return type> method name (method parameters if any)
{
    Block of statements;
}

For example:

class Account {

    static int bal = 0;
    synchronized static void deposit(int amt) {
        bal = bal + amt;
        System.out.println("CURRENT BALANCE = " + bal);
    }
};

2. Synchronized block:

This is an alternative technique for obtaining the concept of synchronization instead of synchronized methods.

When we inherit non-synchronized methods from either base class or interface into the derived class, we cannot make the inherited method as synchronized. Hence, we must use synchronized blocks.

Syntax:

synchronized (object of current class)
{
    Block of statement(s);
}

For example:

abstract class BankOp {

    abstract void deposit(int amt);// p a instance
};

class Account extends BankOp {
    int bal = 0;

    public void deposit(int amt) {
        synchronized (this)
            {
                bal = bal + amt;
                System.out.println("current value=" + bal);
            }
        }
    }

Write a synchronization program in which there exist an account, there exist 'n' number of customers and all the customers want to deposit 10 rupees to the existing balance of account.

Answer:

class Account {

    private int bal = 0;

    synchronized void deposit(int amt) {
        bal = bal + amt;
        System.out.println("CURRENT BALANCE=" + bal);
    }

    int getBal() {
        return (bal);
    }
};

class cust extends Thread {

    Account ac;// has-a relationship 
    cust (Account ac)
    {
        this.ac = ac;
    }
    public void run() {
        ac.deposit(10);
    }
};

class SyncDemo {

    public static final int noc = 5;

    public static void main(String[] args) {
        Account ac = new Account();
        cust cu[] = new cust[noc];
        for (int i = 0; i < noc; i++) {
            cu[i] = new cust(ac);// giving account object 'ac' to each & every customer object
        }
        for (int i = 0; i < noc; i++) {
            cu[i].start();
        }
        for (int i = 0; i < noc; i++) {
            System.out.println("IS ALIVE..? " + cu[i].isAlive());
        }
        try {
            for (int i = 0; i < noc; i++) {
                cu[i].join();
            }
        } catch (InterruptedException ie) {
            System.out.println(ie);
        }
        for (int i = 0; i < noc; i++) {
            System.out.println("IS ALIVE..? " + cu[i].isAlive());
        }
        System.out.println("TOTAL BALANCE=" + ac.getBal());
    }
};

Output:

IS ALIVE..? true 
IS ALIVE..? true 
IS ALIVE..? true 
IS ALIVE..? true 
CURRENT BALANCE=10 
CURRENT BALANCE=20 
CURRENT BALANCE=30 
CURRENT BALANCE=40 
CURRENT BALANCE=50
IS ALIVE..? false 
IS ALIVE..? false 
IS ALIVE..? false 
IS ALIVE..? false 
IS ALIVE..? false 
IS ALIVE..? false 
TOTAL BALANCE=50

Note:

If we execute the above program on single user operating systems it is mandatory for the JAVA programmer to write synchronized keyword since user operating system cannot take care about synchronization by default. Whereas if we run the above program in multi user or threaded operating systems we need not to use a keyword synchronized (optional).

It is always recommended to write synchronized keyword irrespective which ever operating system we use.

Inter thread communication:

If two or more threads are exchanging the data then that communication is known as inter thread communication. In inter thread communication; an output of one thread is given as an input to another thread. In order to develop inter thread communication applications we must make use of a class called java.lang.Object

inter thread communication

Methods in java.lang.Object:

  1. public void wait (long msec)
  2. public void wait (long msec, int nanosec)
  3. public void wait ()
  4. public void notify ()
  5. public void notifyAll ()

Methods 1 and 2 are used for making the thread to wait for some period of time. Once the waiting time is over automatically the thread will come from waiting state to ready state. Method 3 is used for making the thread to wait without specifying waiting time. Method 4 is used for bringing a single waiting thread into ready state. Method 5 is used for bringing all the threads from waiting state to ready state.

consumer program

Develop producer consumer program by using inter thread communication?

Answer:

class Q {

    int n;
    boolean valset;

    synchronized void put(int i) {
        try {
            if (valset) {
                wait();
            }
        } catch (InterruptedException ie) {
            System.out.println(ie);
        }
        n = i;
        System.out.println("PUT=" + i);
        valset = true;
        notify();
    }// put

    synchronized int get() {
        try {
            if (!valset) {
                wait();
            }
        } catch (InterruptedException ie) {
            System.out.println(ie);
        }
        System.out.println("GET=" + n);
        valset = false;
        notify();
        return (n);
    }//get
};// Q
class Producer implements Runnable {

    Q q;
    Thread t;

    Producer(Q q) {
        this.q = q;
        t = new Thread(this, "Producer");
        t.start();
    }

    public void run() {
        int i = 0;
        System.out.println("NAME OF THE THREAD = " + t.getName());
        while (true) {
            q.put(++i);
        }
    }
};// Producer
class Consumer implements Runnable {

    Q q;
    Thread t;

    Consumer(Q q) {
        this.q = q;
        t = new Thread(this, "Consumer");
        t.start();
    }

    public void run() {
        System.out.println("NAME OF THE THREAD = " + t.getName());
        while (true) {
            int i = q.get();
        }
    }
};// Consumer 
class PCDemo {

    public static void main(String[] args) {
        Q q = new Q();
        Producer p = new Producer(q);
        Consumer c = new Consumer(q);
    }
};// PCDemo