Month: September 2016

Java Thread Synchronization – Print Even and Odd in Order

Java Thread Synchronization is one of the most important concepts that every Java Developer should know. Any developer could easily talk about Threads at a high level but synchronizing threads is a tricky part.In this article lets see the intrinsics of thread synchronization using an example.

The problem statement of the example is “There are two threads one which prints only Even Numbers and other that prints Odd Numbers until 10. Synchronize the threads such that the numbers are printed in sequence from 0 to 10.”

The solution is below. Let us break the code and learn the synchronization concepts of Java Threads.

Runnable Interface: The Thread Classes “EvenThread” and “OddThread” implement Runnable interface which tells JVM that these classes behave as Threads. The alternate way of creating a thread class is by extending Thread class, which is considered bad practice because Java does not allow “multiple inheritance” and hence limiting the custom Thread class from extending any other required class and moreover the developer is not going to extend the functionality of Thread class for which the inheritance is intended for.

Thread Creation: The thread class is instantiated by creating a new Thread and passing the Runnable object to it.

run method: The method from Runnable interface that needs to be implemented in the thread class. This method contains the logic of the core work that the thread does.

start method: This method moves the Thread from New state to Runnable state making is part of Runnable pool and based on the scheduling algorithm & CPU availability the thread starts running.

NOTE: The run method cannot be called directly expecting the Thread to start running or behave like the thread . Only invoking the start method will actually start the thread.

synchronized keyword:  This keyword is used to synchronize a method or a block of code. This synchronization ensures that the block of code is accessed only by one Thread at a time hence avoiding any inconsistent object state or wrong computations. The synchronization can be on the class level or object level. In our example, the synchronization is on an object.

lock object: An object is created to be used as  an explicit lock. The same instance of the lock object is passed to two threads( EvenThread & OddThread) that need to be synchronized. A lock is acquired by the Thread on the lock object using the synchronized keyword.

wait method:  The wait method ensures that the thread starts waiting, releasing the lock (monitor) and going to sleep until it is notified by another thread on the same lock to resume its activity. Here the even thread prints the even number and waits until notified by the Odd Thread that it has printed the odd number.

notify method: The notify thread wakes up a thread that is in sleeping state because it was put to wait on the lock (monitor).

volatile keyword: Volatile is access specifier that ensures the value of the variable is always updated to the main memory rather than the thread cache, guaranteeing that all the threads reads updated value. This volatile operations are atomic.

Click here for GitHub Source Code

package com.saranyapk.practice.corejava.thread;

public class ThreadPractice
{
	private static volatile Boolean isEvenStarted = false;

	public static void main( String args[] )
	{
		Object lock = new Object();

		Thread even = new Thread( new ThreadPractice().new EvenThread( lock ) );
		Thread odd = new Thread( new ThreadPractice().new OddThread( lock ) );

		even.start();
		odd.start();

	}

	class EvenThread implements Runnable
	{
		Object lock;

		public EvenThread( Object lock )
		{
			this.lock = lock;
		}

		@Override
		public void run()
		{
			synchronized (lock)
			{
				isEvenStarted = true;

				lock.notify();
			}

			for ( int i = 0; i < 10; i = i + 2 )
			{
				synchronized (lock)
				{
					try
					{
						lock.notify();

						System.out.println( i );

						if ( i < 10 )
						{
							lock.wait();
						}
					}
					catch ( InterruptedException e )
					{
						e.printStackTrace();
					}
				}
			}
		}

	}

	class OddThread implements Runnable
	{
		Object lock;

		public OddThread( Object lock )
		{
			this.lock = lock;

		}

		@Override
		public void run()
		{
			synchronized (lock)
			{
				while ( !isEvenStarted )
				{
					try
					{
						lock.wait();
					}
					catch ( InterruptedException e )
					{
						e.printStackTrace();
					}
				}
			}
			for ( int i = 1; i < 10; i = i + 2 )
			{
				synchronized (lock)
				{
					try
					{

						lock.notify();

						System.out.println( i );

						if ( i < 9 )
						{
							lock.wait();
						}
					}
					catch ( InterruptedException e )
					{
						e.printStackTrace();
					}
				}
			}
		}

	}
}

Advertisements