Java Thread Synchronization

Advertisements

Java Thread Synchronization

Sometimes in multithreading, when two or more threads running simultaneously can generate improper result. For example, we have two methods push() and pop() of stack class.

Definition of push() method


    void push(int n)
    {
        if(top==size-1)
            System.out.print("\n\tStack Overflow");       // Statement 1
        else
        {
            top++;                                        // Statement 2
            stk[top] = n;                                 // Statement 3
        }
    }

Definition of pop() method


    void pop()
    {
        if(top==-1)
            System.out.print("\n\tStack Underflow");
        else
        {
            System.out.print("\n\t" + stk[top] + " is deleted.");// Statement 4

            top--;                                               // Statement 5
         }
    }

As we know, in multithreading, two or more threads runs simultaneously. Suppose we have two threads thread1 and thread2 which will invoke push() and pop() method respectively. During execution of thred1, statement 2 increments the value of top and before inserting the value of n into stack, thread scheduler release the current thread thread1 and executes an another thread thread2. This means pop() method will delete the value, which doesn't exists.

To avoid these kind of situations, we use thread synchronization. In thread synchronization, whenever a thread will get execute, no other thread will get a chance to execute until the current thread will not get executed completely.

Example of thread without Synchronization


//ThreadWithoutSynchronizationDemo.java

    class Pattern
    {

        public void DisplayA()
        {
            for(int i=1;i<=50;i++)
            System.out.print("A");
        }

        public void DisplayB()
        {
            for(int i=1;i<=50;i++)
            System.out.print("B");
        }

        public void DisplayC()
        {
            for(int i=1;i<=50;i++)
            System.out.print("C");
        }
    }

    class ThreadA implements Runnable
    {
        Pattern P;

        ThreadA(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayA();
        }
    }

    class ThreadB implements Runnable
    {

        Pattern P;

        ThreadB(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayB();
        }
    }

    class ThreadC implements Runnable
    {

        Pattern P;

        ThreadC(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayC();
        }
    }

    class ThreadWithoutSynchronizationDemo
    {
        public static void main(String arg[])
        {

            Pattern P = new Pattern();

            ThreadA A = new ThreadA(P);
            ThreadB B = new ThreadB(P);
            ThreadC C = new ThreadC(P);


            Thread t1 = new Thread(A);
            Thread t2 = new Thread(B);
            Thread t3 = new Thread(C);

            t1.start();
            t2.start();
            t3.start();

        }
    }

    Output 1:
    AAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBCCCCCCCCCCCCCC
    CCCBBBBBBBBBBBBBBCCCCCCCC

    Output 2:
    AABBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAA
    CCCCCCCCCCCCCCCCCCCCCCCCC

    Output 3:
    AAAAAAAABACABAACABAACABACCCCCCCCCCCCCCCCCCCCCCAAAA
    ABAAABBBBBBBBBBBBBBBBBBBB

As shown in above output, all threads are running simultaneously.

Example of thread with Synchronization


//ThreadWithSynchronizationDemo.java

    class Pattern
    {

        public synchronized void DisplayA()             // Statement 1
        {
            for(int i=1;i<=50;i++)
            System.out.print("A");
        }

        public synchronized void DisplayB()             // Statement 2
        {
            for(int i=1;i<=50;i++)
            System.out.print("B");
        }

        public void DisplayC()
        {
            synchronized(this)                                      // Statement 3
            {
                for(int i=1;i<=50;i++)
                System.out.print("C");
            }
        }
    }

    class ThreadA implements Runnable
    {
        Pattern P;

        ThreadA(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayA();
        }
    }

    class ThreadB implements Runnable
    {

        Pattern P;

        ThreadB(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayB();
        }
    }

    class ThreadC implements Runnable
    {

        Pattern P;

        ThreadC(Pattern P)
        {
            this.P = P;
        }

        public void run()
        {
            P.DisplayC();
        }
    }

    class ThreadWithSynchronizationDemo
    {
        public static void main(String arg[])
        {

            Pattern P = new Pattern();

            ThreadA A = new ThreadA(P);
            ThreadB B = new ThreadB(P);
            ThreadC C = new ThreadC(P);


            Thread t1 = new Thread(A);
            Thread t2 = new Thread(B);
            Thread t3 = new Thread(C);

            t1.start();
            t2.start();
            t3.start();

        }
    }

    Output 1:
    AAAAAAAAAAAAAAAAAAAAAAAAACCCCCCCCCCCCCCC
    CCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBBBBB

    Output 2:
    BBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAA
    AAAAAAAAAACCCCCCCCCCCCCCCCCCCCCCCCC

    Output 3:
    AAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBB
    BBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCC

As shown in above output, only one thread is running at a time.

To implement synchronization, we must define method with synchronized keyword as shown in statement 1 and 2.

We can also define synchronized block to implement synchronization as shown in statement 3.

Advertisement