Synchronized keyword is not working in java because the thread lock object is not correctly attached to the thread. Because of this, the Java thread synchronisation doesn’t work as expected. The main reason is that each thread will create a new object and lock the object. There’s no synchronisation going to happen.
The java thread synchronization is not working properly when the synchronized keyword is used to synchronize multiple threads to access a common resource. If the thread lock object is not correctly attached to the thread, the java thread synchronization will not work as expected.
Synchronization is a mechanism that won’t allow more than one thread for a resource at any point in time. Multiple threads attempt to access the same resource in multi-threaded environments, resulting in erroneous and unexpected results. Synchronization manages threads for sequential access to resources in order to avoid this.
Synchronization uses a locking mechanism to control threads to access a common resource at any point in time. Synchronized keyword lock an object for a thread and no other threads are able to lock it before the first thread is released. Improper coding to lock an object will result in a java thread synchronization failure.
Java Synchronization not working
The synchronised keyword is used to synchronise two or more threads to access a shared resource one thread at a time. In the following example, the synchronised keyword is used to synchronise two threads. But synchronisation doesn’t work as expected.
package com.yawintutor;
public class MyThread extends Thread {
public Object lockingObject=new Object();
public void run() {
synchronized (lockingObject) {
for (int i = 0; i < 3; i++) {
System.out.println("Thread name : " + getName() + " count : " + i);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
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 synchronisation only works if the object is locked by all threads. If the java threads are locks for different instances of class objects, then the synchronisation 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 the access sequence of the Java resource. If threads lock separate objects in the class, the synchronisation will not happen.
Synchronize using static object
The synchronised keyword is used to sync java threads. The synchronised keyword uses a java object to lock the thread and does not allow other threads to enter the synchronised block at the same time. If the locking object is a static object, a single instance of the object will be created. As a result, the synchronisation will work in java.
package com.yawintutor;
public class MyThread extends Thread {
public static Object lockingObject=new Object();
public void run() {
synchronized (lockingObject) {
for (int i = 0; i < 3; i++) {
System.out.println("Thread name : " + getName() + " count : " + i);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
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
Synchronize using String object
The java String is an immutable object. The java strings are created newly. The java string can not be modified, 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 MyThread extends Thread {
public String lockingObject="test";
public void run() {
synchronized (lockingObject) {
for (int i = 0; i < 3; i++) {
System.out.println("Thread name : " + getName() + " count : " + i);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
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
Synchronize using Constants
The java string constants that are created to access any where in the application. In this method , two separate thread implementations can be synchronised in Java. For example , if two threads a1, a2 are created using thread class A, and two threads b1, b2 is created using thread class B, then all four threads a1, a2, b1 , b2 can be synchronised using constant value.
package com.yawintutor;
public class Constant {
public static String lockingObject="test";
}
package com.yawintutor;
public class MyThread extends Thread {
public void run() {
synchronized (Constant.lockingObject) {
for (int i = 0; i < 3; i++) {
System.out.println("Thread name : " + getName() + " count : " + i);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
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
Synchronize using Singleton Object
The singleton java object will make sure that one instance of the class is created. The singleton object can be used for java lock to synchronise java threads. The java threads will get the same singleton object that will be used to lock the synchronised block.