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

Java Method Synchronization is a mechanism that will not allow more than one thread to execute a java method at any point in time. Multiple threads attempt to execute the java method in multi-threaded environments, resulting in incorrect and unpredictable results. Method synchronization handles threads for sequential access to run a method in order to prevent this.

Synchronization uses a locking mechanism to control threads to access the java method at any point in time. Synchronized keyword lockes the java method for a thread and no other threads can lock it until the first thread is released. Improper coding to lock a java method will result in a java thread synchronization failure.



Java Synchronized Method not working

The synchronised keyword is used by the Java method to synchronise the Java method. The synchronised java method will be executed with a thread at a time. If another thread is attempting to execute the method, the lock in the synchronised method will not allow it to run and wait until the lock is released. The code below is using the synchronized method that is not working as expected.

package com.yawintutor;

public class NumberPrinter {
	public synchronized void print() {
		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 {
	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 1 count : 0
Thread name : THREAD 2 count : 0
Thread name : THREAD 2 count : 1
Thread name : THREAD 1 count : 1
Thread name : THREAD 2 count : 2
Thread name : THREAD 1 count : 2


Root Cause

Java method synchronization only works if the instance method is locked by all threads. If the java threads are locks for different instances of class methods, then the synchronization will not work. All java threads should attempt to lock the same object method, and if the lock is not available, the thread will wait until the lock is released. This will ensure the sequence method access in the Java class. If threads lock different instance methods in the class, there will be no synchronization.



Synchronized Method Using static method

The java static method is a single instance of the method reference across class objects. The static keyword in the method will allow only one instance of the method reference to be created. If the synchronised method is configured as a static synchronised method, all threads will invoke the method from the same memory reference. If the synchronised java method is locked by a thread, other threads should wait until the lock is released.

package com.yawintutor;

public class NumberPrinter {
	public static synchronized void print() {
		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 {
	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 Method Using static class object

The java thread will create a new class instance that interns will create a new java synchronised method instance. If a thread locks the synchronised java method, the other java method locks another java method instance. The synchronisation will therefore not work in the java threads. If the class is created as a static object, the java method in the class will have a single instance.

package com.yawintutor;

public class NumberPrinter {
	public synchronized void print() {
		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 {
	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 Method Using single class instance

If a single instance of the class is used in threads, the lock will be generated on the same reference of the java method. Therefore, the synchronisation of the Java method 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 {
	public synchronized void print() {
		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;

	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