Synchronized block is not working in java because the lock on the synchronised block is not attached to a single object. When the Java code block is synchronised with the synchronised keyword, the threads are synchronised to access the Java code block. If the java synchronised block lock is not properly attached to a java object, the java synchronised block will not work as expected.

Java Synchronized Block is a mechanism that does not allow more than one thread to execute a Java code block at any time. Multiple threads try to execute java code in multi-threaded environments, resulting in incorrect and unpredictable outcomes. Synchronized block manages threads for sequential access to run a code block to prevent this from happening.

Synchronization uses a locking mechanism to manage threads to access the Java code at any time. Synchronized keyword locks the java code for a thread, and no other threads can lock it before the first thread is released. Improper coding to lock a java method will result in a synchronised java block failure.



Java Synchronized Block not working

The synchronized keyword is used in the Java code block to synchronize the Java code. The synchronized java block will be executed with a thread at a time. If another thread tries to execute a code block, the lock in the synchronized block would not allow it to run and wait until the lock is released. The code below uses a synchronized block that is not working as expected.

package com.yawintutor;

public class NumberPrinter {
	
	public void print() {
		synchronized (this) {
			Thread thread = Thread.currentThread();
			for (int i = 0; i < 3; i++) {
				System.out.println("Thread name : " + thread.getName() + " count : " + i);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
package com.yawintutor;

public class MyThread extends Thread {
	public NumberPrinter printer = new NumberPrinter();

	public void run() {
		printer.print();
	}
}
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 2 count : 0
Thread name : THREAD 1 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


Root Cause

The Java synchronized block can only work if the block is locked with the object by all threads. If the java threads are locks for different class objects, the synchronization will not work.

All java threads should try to lock the same object, and if the lock is not available, the thread will wait until the lock is released. This will ensure sequence access to the code in the Java synchronized block. If threads lock up different instance objects in the class, there will be no synchronization.



Synchronized Block using Class Name

The Java synchronized block should be locked using an instance of an object. The same instance should be used for all threads. Otherwise, the name of the class should be used to synchronize the code block to run multiple threads in sequential order.

package com.yawintutor;

public class NumberPrinter {
	
	public void print() {
		synchronized (NumberPrinter.class) {
			Thread thread = Thread.currentThread();
			for (int i = 0; i < 3; i++) {
				System.out.println("Thread name : " + thread.getName() + " count : " + i);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
package com.yawintutor;

public class MyThread extends Thread {
	public NumberPrinter printer = new NumberPrinter();

	public void run() {
		printer.print();
	}
}

Output

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


Synchronized Block using String variable

The java String is an immutable object. The java string can not be changed, instead the modified string can be created.If two strings are assigned the same value of the string, both will point to the same memory address of the string. If the string is locked, all threads that attempt to lock the same string will wait until the lock is released.

package com.yawintutor;

public class NumberPrinter {
	
	public void print() {
		synchronized ("test") {
			Thread thread = Thread.currentThread();
			for (int i = 0; i < 3; i++) {
				System.out.println("Thread name : " + thread.getName() + " count : " + i);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
package com.yawintutor;

public class MyThread extends Thread {
	public NumberPrinter printer = new NumberPrinter();

	public void run() {
		printer.print();
	}
}

Output

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


Synchronized Block using Static Class Member Variable

The synchronized block can use a static class member variable to lock the thread. The static class variable will be assigned to an object and will not allow another instance of an object to be generated. The first thread will lock the synchronized block with the static variable and the other threads will wait until the lock is released.

package com.yawintutor;

public class NumberPrinter {
	private static String lockObject ="test";
	
	public void print() {
		synchronized (lockObject) {
			Thread thread = Thread.currentThread();
			for (int i = 0; i < 3; i++) {
				System.out.println("Thread name : " + thread.getName() + " count : " + i);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
package com.yawintutor;

public class MyThread extends Thread {
	public NumberPrinter printer = new NumberPrinter();

	public void run() {
		printer.print();
	}
}

Output

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


Synchronized Block using Static Class Object

The synchronized block will use a class member variable to lock the thread. The class instance should be assigned to a static variable that should be used in the threads. The static class instance object will maintain a object and will not allow to create another class instance. The first thread will lock the synchronized block with the member variable and the other threads will wait until the lock is released.

package com.yawintutor;

public class NumberPrinter {
	private String lockObject =new String("test");
	
	public void print() {
		synchronized (lockObject) {
			Thread thread = Thread.currentThread();
			for (int i = 0; i < 3; i++) {
				System.out.println("Thread name : " + thread.getName() + " count : " + i);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
package com.yawintutor;

public class MyThread extends Thread {
	public static NumberPrinter printer = new NumberPrinter();

	public void run() {
		printer.print();
	}
}

Output

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


Synchronized Block using Class Instance object

If a single instance of the class is used in threads, the lock will be generated on the same reference of the java class object. Therefore, the synchronisation of the Java code will work. In this case , a single instance created in the java application framework can be used. The application framework will create and maintain a single class instance.

package com.yawintutor;

public class NumberPrinter {
	private String lockObject =new String("test");
	
	public void print() {
		synchronized (lockObject) {
			Thread thread = Thread.currentThread();
			for (int i = 0; i < 3; i++) {
				System.out.println("Thread name : " + thread.getName() + " count : " + i);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
package com.yawintutor;

public class MyThread extends Thread {
	public NumberPrinter printer = null;

	public void run() {
		printer.print();
	}
}
package com.yawintutor;

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

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

	}
}

Output

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



Leave a Reply