Synchronization in Java

Java Synchronization

Synchronization in Java

Thread communication is sharing information between one or more object, they share their information via methods or properties. This kind of communication is extremely important and may have some interference during application run time.

Synchronization is the most important topic when it comes to the thread communication. It should be handled very carefully in multi threaded environment.

In this tutorial, we will discuss about synchronization but before that we will discuss about locking mechanism between objects in java programming and how they are useful in thread communication or synchronization.


What is Locking


Ever thought that how synchronization actually works, simply by using the concept of locking. Each and every object in java has build in lock that only activates when you use the concept of synchronization in java. Actually when we enter into the synchronization method or block, object automatically acquires the lock.

There is one more term comes into the role which is “Monitor”, actually block and monitor both are different things in java.

There can only be one and only one lock per object at a time, if one object has acquired the lock then no other thread can take it until it has been released from the object which has acquired it before. That means, no other thread can enter into the synchronization method or block until they have lock with them.

Technically speaking, releasing the lock means the execution inside the synchronization block or method has been completed and lock has been released from the current object.

What is Synchronization in java


By using the concept of locking, Synchronization provides great access control when two or more threads try to access the same resource simultaneously in multi thread environment. Synchronization helps us to prevent thread interference and memory consistency errors.


Some important things to know about Synchronization and locking in java

Before we try to implement synchronization in our program, let’s discuss some important things about it.

  1. You can only synchronize the methods and blocks, you can not synchronize the variables or classes.
  2. You can only synchronize the block of code or whole method in java. There is not need to synchronize all of the methods, only synchronize which is necessary.
  3. Each object in java has one and only one lock and in order to access synchronize method or block, you need the object lock.
  4. If multiple thread trying to access the same resource at the same time, only one thread can access it which has lock other threads will have to wait for their turn.
  5. If sleep method is invoked on any thread object, it actually doesn’t release the lock.

Ways to implement synchronization in java


There is multiple ways which you can use in order to implement synchronization in java as per your requirement. You should be careful while implementing synchronization in java otherwise it can lead the performances issues in your code as well. See blow image.



Java Synchronization





So let’s discuss them one by one.

Synchronized Methods


You can use synchronization on method. Any object which needs to execute the synchronized method needs a lock with it. Let’s see the example of synchronization with and without synchronized method.

Example without Synchronized method

class SyncDemo {
 
 public void showNumbers(String threadName) {
   try {
     for(int i=1; i<=5; i++) {
       System.out.println("Printing Number from the thread (" + threadName + ") : " + i);
       Thread.sleep(1000);
     }
   } catch(Exception e) {
     e.printStackTrace();
   }
 }

}

class Thread1 extends Thread {
 
 private SyncDemo syncDemo;
 
 public Thread1(SyncDemo d) {
 this.syncDemo = d;
 }
 
 public void run() {
 this.syncDemo.showNumbers(this.getName());
 }
}

class Thread2 extends Thread {
 
 private SyncDemo syncDemo;
 
 public Thread2(SyncDemo d) {
 this.syncDemo = d;
 }
 
 public void run() {
 this.syncDemo.showNumbers(this.getName());
 }
}

public class SyncExample {

 public static void main(String arg[]) {

 SyncDemo syncDemo = new SyncDemo();
 
 Thread1 t1 = new Thread1(syncDemo);
 Thread2 t2 = new Thread2(syncDemo);
 
 t1.setName("Thread 1");
 t2.setName("Thread 2");
 
 t1.start();
 t2.start();
 }
}

Output :
Printing Number from the thread (Thread 1) : 1
Printing Number from the thread (Thread 2) : 1
Printing Number from the thread (Thread 1) : 2
Printing Number from the thread (Thread 2) : 2
Printing Number from the thread (Thread 1) : 3
Printing Number from the thread (Thread 2) : 3
Printing Number from the thread (Thread 1) : 4
Printing Number from the thread (Thread 2) : 4
Printing Number from the thread (Thread 2) : 5
Printing Number from the thread (Thread 1) : 5


Can you see the inconsistency in the output while printing numbers. Multiple threads are accessing the same resource causing the inconsistency and thread interference. You can overcome from this problem by simply using synchronized methods in java.

Example with synchronized method

class SyncDemo {
 
 public synchronized void showNumbers(String threadName) {
   try {
     for(int i=1; i<=5; i++) {
       System.out.println("Printing Number from the thread (" + threadName + ") : " + i);
       Thread.sleep(1000);
     }
   } catch(Exception e) {
     e.printStackTrace();
   }
 }

}

class Thread1 extends Thread {
 
 private SyncDemo syncDemo;
 
 public Thread1(SyncDemo d) {
 this.syncDemo = d;
 }
 
 public void run() {
 this.syncDemo.showNumbers(this.getName());
 }
}

class Thread2 extends Thread {
 
 private SyncDemo syncDemo;
 
 public Thread2(SyncDemo d) {
 this.syncDemo = d;
 }
 
 public void run() {
 this.syncDemo.showNumbers(this.getName());
 }
}

public class SyncExample {

 public static void main(String arg[]) {

 SyncDemo syncDemo = new SyncDemo();
 
 Thread1 t1 = new Thread1(syncDemo);
 Thread2 t2 = new Thread2(syncDemo);
 
 t1.setName("Thread 1");
 t2.setName("Thread 2");
 
 t1.start();
 t2.start();
 }
}
Output:
Printing Number from the thread (Thread 1) : 1
Printing Number from the thread (Thread 1) : 2
Printing Number from the thread (Thread 1) : 3
Printing Number from the thread (Thread 1) : 4
Printing Number from the thread (Thread 1) : 5
Printing Number from the thread (Thread 2) : 1
Printing Number from the thread (Thread 2) : 2
Printing Number from the thread (Thread 2) : 3
Printing Number from the thread (Thread 2) : 4
Printing Number from the thread (Thread 2) : 5


See the output above, only one thread can access the resource at a time. This is how we implement synchronized method in java.

Synchronized Block in java


There can be a situation where you need performance and synchronization both at a time in your particular code. Then Java has solution for that as well, with synchronized block you can synchronize a part of your code in method. So that multiple thread can access the information which don’t need to be synchronized. 

For example, suppose read and write both operation is being performed in your particular method then you can synchronize the write operation and let the thread read the information.

When you use synchronized block in your code then you need to tell which object’s lock you want to use as lock in your synchronized piece of code. That way, you can also use third party object as a lock.

Example on synchronized block

class SyncDemo {
 
 public void showNumbers(String threadName) {
   synchronized(this) {
   try {
     for(int i=1; i<=5; i++) {
       System.out.println("Printing Number from the thread (" + threadName + ") : " + i);
       Thread.sleep(1000);
     }
   } catch(Exception e) {
     e.printStackTrace();
   }
   }
 }

}

class Thread1 extends Thread {
 
 private SyncDemo syncDemo;
 
 public Thread1(SyncDemo d) {
 this.syncDemo = d;
 }
 
 public void run() {
 this.syncDemo.showNumbers(this.getName());
 }
}

class Thread2 extends Thread {
 
 private SyncDemo syncDemo;
 
 public Thread2(SyncDemo d) {
 this.syncDemo = d;
 }
 
 public void run() {
 this.syncDemo.showNumbers(this.getName());
 }
}

public class SyncExample {

 public static void main(String arg[]) {

 SyncDemo syncDemo = new SyncDemo();
 
 Thread1 t1 = new Thread1(syncDemo);
 Thread2 t2 = new Thread2(syncDemo);
 
 t1.setName("Thread 1");
 t2.setName("Thread 2");
 
 t1.start();
 t2.start();
 }
}
Output:
Printing Number from the thread (Thread 1) : 1
Printing Number from the thread (Thread 1) : 2
Printing Number from the thread (Thread 1) : 3
Printing Number from the thread (Thread 1) : 4
Printing Number from the thread (Thread 1) : 5
Printing Number from the thread (Thread 2) : 1
Printing Number from the thread (Thread 2) : 2
Printing Number from the thread (Thread 2) : 3
Printing Number from the thread (Thread 2) : 4
Printing Number from the thread (Thread 2) : 5

As you can see above output will be same as synchronized method.


Then what about static methods


Yes we can synchronize the static methods as well in java. Each and every class loaded in the Java has a corresponding instance of java.lang.Object which is used to represent that class. A lock of java.lang.Object instance is used to protect to protect the static synchronized methods of that class.

There is only single copy of the the data which you will be protecting. So you only need one lock per class for that operation.

Example on static synchronized method

class SyncDemo {
 
 public static synchronized void showNumbers(String threadName) {
   try {
     for(int i=1; i<=5; i++) {
       System.out.println("Printing Number from the thread (" + threadName + ") : " + i);
       Thread.sleep(1000);
     }
   } catch(Exception e) {
     e.printStackTrace();
   }
 }

}

class Thread1 extends Thread {
 public void run() {
 SyncDemo.showNumbers(this.getName());
 }
}

class Thread2 extends Thread {
 public void run() {
 SyncDemo.showNumbers(this.getName());
 }
}

public class SyncExample {

 public static void main(String arg[]) {

 Thread1 t1 = new Thread1();
 Thread2 t2 = new Thread2();
 
 t1.setName("Thread 1");
 t2.setName("Thread 2");
 
 t1.start();
 t2.start();
 }
}
Output:
Printing Number from the thread (Thread 1) : 1
Printing Number from the thread (Thread 1) : 2
Printing Number from the thread (Thread 1) : 3
Printing Number from the thread (Thread 1) : 4
Printing Number from the thread (Thread 1) : 5
Printing Number from the thread (Thread 2) : 1
Printing Number from the thread (Thread 2) : 2
Printing Number from the thread (Thread 2) : 3
Printing Number from the thread (Thread 2) : 4
Printing Number from the thread (Thread 2) : 5

Related Post

Leave a Reply

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