Synchronized Method in Java | Example Program

When we declare a synchronized keyword in the header of a method, it is called synchronized method in Java.

Using the synchronized keyword, we can synchronize all the methods of any class.

When a method is declared as synchronized, JVM creates a monitor (lock). To enter the monitor, the synchronized method is called. The thread that calls the synchronized method first, acquires object lock.

If the object lock is not available, the calling thread is blocked and it has to wait until the lock becomes available.

As long as thread holds lock (monitor), no other thread can enter the synchronized method and will have to wait for the current thread to release the lock on the same object. Look at the below figure to understand better.

Synchronized method in Java

Once a thread completes the execution of code inside the synchronized method, it releases object lock and allows other thread waiting for this lock to proceed.

That is once a thread completes its work using synchronized method, it will hand over to the next thread that is ready to use the same resource.

Syntax to declare Synchronized method in Java


The general syntax to make a method synchronized is as follows:

Syntax:

synchronized data_type method_name()
{
  // Code to be synchronized.
}

For example, if you want to synchronize the code of show() method, add the synchronize before the method name.

synchronized void show()
{
  // statements to be synchronized
}

Since the code inside the method is synchronized, the code will not be available to more than one thread at a time.


Program code 1:

public class Table 
{
void printTable(int n) // Here, method is not synchronized.
{
for(int i = 1; i <= 5; i++)
{  
 System.out.println(n * i);  
 try
 {  
    Thread.sleep(400);  
 }
catch(InterruptedException ie)
{
   System.out.println(ie);
 }  
 }}  
}
public class Thread1 extends Thread
{
  Table t; // Declaration of variable t of class type Table.

// Declare one parameterized constructor and pass variable t as a parameter.
   Thread1(Table t)
   {  
      this.t = t;  
   }  
  public void run()
  {  
    t.printTable(2);  
  }  
}
public class Thread2 extends Thread
{
  Table t;  
  Thread2(Table t)
  {  
    this.t = t;  
  }  
  public void run()
  {  
    t.printTable(10);  
  }  
}
public class UnsynchronizedMethod {
public static void main(String[] args) 
{
// Create an object of class Table.	
    Table obj = new Table();
    Thread1 t1 = new Thread1(obj);
    Thread2 t2 = new Thread2(obj);
      t1.start(); 
      t2.start();
 }
}
Output:
       2
       10
       4
       20
       30
       6
       40
       8
       50
       10

Explanation:

1. The class Table has a method named printTable() which takes a parameter n of Integer type. This method will print the table of 2 and 10. The sleep() method is called inside the printTable() method that causes the current thread to halt for 0.4 sec.

2. The constructor of class Thread1 takes one argument as a reference to an object of class Table.

3. When the first thread starts, run() method is called for execution. The run() method calls printTable() method on the object t of class Table.


4. When the sleep() method is called on the first thread, it pauses thread for 0.4 sec before complete its execution. Meanwhile, thread scheduler switches to the second thread for execution.

Thus, the output of program is in mixed up form and does not get expected results. This is because two threads call the same method printTable() and switch from one thread to another thread without completion of its tasks.


Now let’s modify program 1 where we will declare synchronized keyword before the signature of printTbale() method.

This technique will allow only one thread to access printTable() method to complete its task at a time and prevent another thread to access it.

Thus, we will get the correct output. Look at the following source code to understand better.

Program code 2:

public class Table 
{
 synchronized void printTable(int n) // Here, method is synchronized.
 {
   for(int i = 1; i <= 5; i++)
   {  
     System.out.println(n * i);  
     try
     {  
       Thread.sleep(400);  
     }
    catch(InterruptedException ie)
    {
       System.out.println(ie);
    }  
 }}  
}
public class Thread1 extends Thread
{
  Table t; // Declaration of variable t of class type Table.

// Declare one parameterized constructor and pass variable t as a parameter.
   Thread1(Table t)
   {  
      this.t = t;  
   }  
  public void run()
  {  
     t.printTable(2);  
  }  
}
public class Thread2 extends Thread
{
  Table t;  
  Thread2(Table t)
  {  
    this.t = t;  
  }  
  public void run()
  {  
    t.printTable(10);  
  }  
}
public class SynchronizedMethod {
public static void main(String[] args) 
{
// Create an object of class Table.	
  Table obj = new Table();
  Thread1 t1 = new Thread1(obj);
  Thread2 t2 = new Thread2(obj);
    t1.start(); 
    t2.start();
 }
}
Output:
       2
       4
       6
       8
       10
       10
       20
       30
       40
       50

Explanation:

As you can see in the output, we get the expected output. This is because once the first thread enters into synchronized printTable() method on an instance, the second thread can not enter into synchronized printTable() method on the same instance.

Thus, once the first thread completes its task, then second thread enters into synchronized method to complete its task.


Note:

Simultaneous execution of synchronized methods is possible for two different objects of the same class. Let’s take an example program based on it.

Program code 3:

public class Table 
{
  synchronized void printTable1(int x) // First synchronized method.
  {
    for(int i = 1; i <= 3; i++)
    {  
      System.out.println(x * i);  
      try
      {  
        Thread.sleep(400);  
      }
      catch(InterruptedException ie)
      {
        System.out.println(ie);
      } 
   }
}  
synchronized void printTable2(int y) // Second synchronized method.
{
  for(int j = 1; j <= 3; j++)
  {  
    System.out.println(y * j);  
    try
    {  
      Thread.sleep(400);  
    }
   catch(InterruptedException ie)
   {
      System.out.println(ie);
   }  
  }
} }
public class Thread1 extends Thread
{
  Table t; // Declaration of variable t of class type Table.
  Thread1(Table t)
  {  
     this.t = t;  
  }  
  public void run()
  {  
     t.printTable1(2); // Calling first synchronized method.
   }  
}
public class Thread2 extends Thread
{
 Table t;  
 Thread2(Table t)
 {  
   this.t = t;  
 }  
 public void run()
 {  
   t.printTable2(10); // Calling second synchronized method.
 }  
}
public class SynchronizedMethod {
public static void main(String[] args) 
{
// Create two objects of class Table.	
   Table obj = new Table();
   Table obj2 = new Table();

  Thread1 t1 = new Thread1(obj);
  Thread2 t2 = new Thread2(obj2);
    t1.start(); 
    t2.start();
 }
}
Output:
      2
      10
      4
      20
      6
      30

As you can observe the output, simultaneous execution of two synchronized methods has happened with two different instances of the same class.

Can we synchronize static method in Java?


Yes, a static method can also be synchronized. In this case, the lock is placed on the class, not on the object. The thread will execute the method body only when the lock is placed on the class.

It will hold the lock until it leaves the method body. This is called static synchronization in java.

Let’s take an example program based on it to understand better.

Program code 4:

public class Table 
{
synchronized static void printTable(int x) // Here, static method is synchronized.
{
for(int i = 1; i <= 3; i++)
{  
 System.out.println(x * i);  
 try
 {  
   Thread.sleep(400);  
 }
catch(InterruptedException ie)
{
   System.out.println(ie);
 }  }
}  
}
public class Thread1 extends Thread
{ 
public void run()
{  
   Table.printTable(2); // Calling synchronized static method using class name with passing argument 2.
 }  
}
public class Thread2 extends Thread
{
public void run()
{  
  Table.printTable(10); // Calling synchronized static method using class name with passing argument 10.
 }  
}
public class SynchronizedMethod
{
public static void main(String[] args) 
{
Thread1 t1 = new Thread1();
Thread2 t2 = new Thread2();
 t1.start(); 
 t2.start();
 }
}
Output:
      2
      4
      6
      10
      20
      30

Hope that this tutorial has covered synchronized method in Java with example programs. I hope that you will have understood the basic concepts of the Synchronized method.

In the next tutorial, we will learn synchronized block in Java with example programs. If you get any incorrect in this tutorial, please inform to our team through email. Your email will be precious to us.
Thanks for reading!!!
Next ⇒ Deadlock in Java⇐ PrevNext ⇒

Please share your love