Thread Synchronization in Java

Java Thread Synchronization is a way of synchronising Java threads to access a shared resource in a controlled way. If multiple threads attempt to access a shared resource, due to concurrency problems, they may create unintended outcomes . Java threads are synchronised to prevent unpredictable outcomes. There will be only one thread accessing the shared resource at a time.

Synchronization is a process that at any point in time will not allow more than one thread for a resource. In multi-threaded environment, multiple threads attempt to access the same resource, leading in erroneous and unforeseen outcomes. To prevent this, Synchronization controls threads for sequential access to resources.



Threads without Synchronization

To understand Synchronization, let’s start with threads running in parallel without synchronization. Threads will run parallel and attempt to access resource concurrently. The outcomes are printed in unpredictable order as shown in the below example.

The order of the execution of the thread would be unpredictable. If you run the below example several times, you will see different thread execution order. The thread execution is dependent on the operating system or java process cpu allocation.

MyThread.java

package com.yawintutor;

public class MyThread extends Thread {

	public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println("Thread name : " + getName() + " count : " + i);
			try {
				sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

MyThreadMain.java

package com.yawintutor;

public class MyThreadMain {
	public static void main(String[] args) throws Exception {

		MyThread thread1 = new MyThread();
		thread1.setName("THREAD 1");
		thread1.start();

		MyThread thread2 = new MyThread();
		thread2.setName("THREAD 2");
		thread2.start();

	}
}

Output

Thread name : THREAD 1 count : 0
Thread name : THREAD 2 count : 0
Thread name : THREAD 1 count : 1
Thread name : THREAD 2 count : 1
Thread name : THREAD 2 count : 2
Thread name : THREAD 1 count : 2
Thread name : THREAD 2 count : 3
Thread name : THREAD 1 count : 3
Thread name : THREAD 2 count : 4
Thread name : THREAD 1 count : 4


Synchronized Threads

There is a controlled execution of synchronized threads. Threads are performed one after the other to access the resource. In this example, The data is printed one thread after another thread.

In the example below, an object created by the main method, is used as a locking object. The locking object reference is passed and assigned in a local variable in both threads. If a thread executes the run method, a synchronised keyword locks the string object first. Then the synchronised block starts executing the statement. If the synchronised block is executed, the locked object will be released.

If another thread is attempting to run the run method, the thread will wait until the locked object is released in a synchronised block. If the locked object is released, the synchronised keyword locks the object and proceeds to execute the synchronized block.

SyncThread.java

package com.yawintutor;

public class SyncThread extends Thread {
	public String lockingObject;

	public void run() {
		synchronized (lockingObject) {
			for (int i = 0; i < 5; i++) {
				System.out.println("Thread name : " + getName() + " count : " + i);
				try {
					sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

SyncThreadMain.java

package com.yawintutor;

public class SyncThreadMain {
	public static void main(String[] args) throws Exception {
		String obj = "lockobject";

		SyncThread thread1 = new SyncThread();
		thread1.setName("THREAD 1");
		thread1.lockingObject = obj;
		thread1.start();

		SyncThread thread2 = new SyncThread();
		thread2.setName("THREAD 2");
		thread2.lockingObject = obj;
		thread2.start();
	}
}

Output

Thread name : THREAD 1 count : 0
Thread name : THREAD 1 count : 1
Thread name : THREAD 1 count : 2
Thread name : THREAD 1 count : 3
Thread name : THREAD 1 count : 4
Thread name : THREAD 2 count : 0
Thread name : THREAD 2 count : 1
Thread name : THREAD 2 count : 2
Thread name : THREAD 2 count : 3
Thread name : THREAD 2 count : 4


Synchronized Threads using static lock

The static lock variable creates an instance of the class. The static variable holds the same object across all class instances. If the static variable is used in the synchronised keyword to lock the thread, all threads will wait until the lock is released.

SyncThread.java

package com.yawintutor;

public class SyncThread extends Thread {
	public static String lockingObject="";

	public void run() {
		synchronized (lockingObject) {
			for (int i = 0; i < 5; i++) {
				System.out.println("Thread name : " + getName() + " count : " + i);
				try {
					sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

SyncThreadMain.java

package com.yawintutor;

public class SyncThreadMain {
	public static void main(String[] args) throws Exception {
		SyncThread thread1 = new SyncThread();
		thread1.setName("THREAD 1");
		thread1.start();

		SyncThread thread2 = new SyncThread();
		thread2.setName("THREAD 2");
		thread2.start();
	}
}

Output

Thread name : THREAD 1 count : 0
Thread name : THREAD 1 count : 1
Thread name : THREAD 1 count : 2
Thread name : THREAD 1 count : 3
Thread name : THREAD 1 count : 4
Thread name : THREAD 2 count : 0
Thread name : THREAD 2 count : 1
Thread name : THREAD 2 count : 2
Thread name : THREAD 2 count : 3
Thread name : THREAD 2 count : 4



Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *