Tuesday, May 21, 2019

Synchronization in Java - Synchronized Method And Block

In this post we'll see how thread synchronization is done using synchronized keyword in Java.

In a multithreaded environment when multiple threads are trying to access a shared resource we need to have some mechanism to ensure that the resource will be used only by one thread at a time. The process by which it is ensured is called synchronization in multi-threading.


How synchronization in Java works

For achieving synchronization in Java concept of monitor is used. Every object created in Java has one associated monitor (mutually exclusive lock). At any given time Only one thread can own the monitor.

The Java programming language provides two basic synchronization idioms using the synchronized keyword.

  • synchronized methods
  • synchronized statements (also known as synchronized blocks).

Before any thread executes the code which is with in a synchronized method (or synchronized block) compiler provides instructions to acquire the lock on the specified object.

When any thread acquires a lock it is said to have entered the monitor. All other threads which need to execute the same shared piece of code (locked monitor) will be suspended until the thread which initially acquired the lock releases it.

Where can we use synchronized keyword in Java

As already stated synchronized keyword can be used with methods or blocks in Java. This can be further divided into use with instance methods and static methods. Which means, we can have four different ways synchronized keyword in Java can be used.

  • instance method
  • An enclosed code block with in an instance method (Synchronized block).
  • static method
  • An enclosed code block with in a static method.

Refer Static Synchronization in Java Multi-Threading to see how to use synchronization with static method and block and why it is needed.

Let's see where and why we should use a specific type of synchronized method or block.

Synchronized Method in Java

We can synchronize a method by adding synchronized keyword within a method signature.

General Form of synchronized instance method

synchronized <returntype> method_name(parameter_list){
  ..
  ..
}

Java synchronized method example

Let's see an example code where first we write the code without synchronizing the method and later we have the same code where method is synchronized.

Here we have a class Message whose object will be shared among threads. In class Message there is a method displayMsg and you want one thread to finish printing the message with in the method then only another thread starts executing the method.

Code when synchronized keyword is not used

// This class' shared object will be accessed by threads
class Message{
 public void displayMsg(String msg){
   System.out.println("Inside displayMsg method " + Thread.currentThread().getName());
   System.out.println("**" + msg); 
   try {
      Thread.sleep(10);
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
   System.out.println("*");
 }
}
 
class MyClass implements Runnable{
  Thread t;
  Message msg;
  String message;
  MyClass(Message msg, String str){ 
    this.msg = msg;
    this.message = str;
    // creating threads, 4 threads will be created 
    // all sharing the same object msg
    t = new Thread(this);
    t.start();
  }
  @Override
  public void run() {
     msg.displayMsg(message);
  }
}

public class SynchronizedDemo {
  public static void main(String[] args) {
    Message msg = new Message();
    MyClass mc1 = new MyClass(msg, "I");
    MyClass mc2 = new MyClass(msg, "am");
    MyClass mc3 = new MyClass(msg, "not");
    MyClass mc4 = new MyClass(msg, "synchronized");
  }
}

Output

I got the following output, for you output may differ as it depends upon which thread is picked first.

Inside displayMsg method Thread-0
Inside displayMsg method Thread-3
**synchronized
Inside displayMsg method Thread-1
**am
Inside displayMsg method Thread-2
**not
**I
*
*
*
*

It can be seen how output is all jumbled, because all the 4 threads share the same object and synchronized keyword is not used to ensure that only single thread has the lock on the object and only that thread can execute the method.

Code when synchronized is used

If we synchronize a method only a single thread will access the method at the given time. In that case the displayMsg() method will look like -

class Message{
    public synchronized void displayMsg(String msg){
        System.out.println("Inside displayMsg method " + Thread.currentThread().getName());
        System.out.print("**" + msg);        
        try {
            Thread.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("*");
    }
}

Output

Inside displayMsg method Thread-0
**I*
Inside displayMsg method Thread-1
**am*
Inside displayMsg method Thread-2
**not*
Inside displayMsg method Thread-3
**synchronized*

Now it can be seen how one thread finishes its execution then only another thread starts its execution of the method. Though which thread is picked first is up to the scheduler that's why the message may not print correctly but the point here is that whichever thread enters the synchronized method that finishes then only the next thread starts its execution.

Please note that a synchronized instance method is synchronized on the instance(object) of the class. So, if a class has more than one object then one thread at a time can enter each object's synchronized method.

Synchronized statement (block) in Java

You don't need to synchronize the whole method, let's say we have a 100 line code method, out of which critical section (shared resource) comprises of 7 lines only then it makes sense to synchronize those 7 lines only rather than the whole method. That way we can improve performance.

synchronized statements must specify the object that provides the intrinsic lock.

General Form of Synchronized statement (synchronized block)

synchronized(object_reference){
  // code block
}

Though it is also possible to synchronize on a string but it is considered a bad idea as "Literal strings within different classes in different packages likewise represent references to the same String object." See this for reference - http://www.javalobby.org/java/forums/t96352.html

Java synchronized block example

If we use the same example used above with synchronized method it can be changed to use synchronized block like this-

//This class' shared object will be accessed by threads
class Message{
    public void displayMsg(String msg){
        System.out.println("Inside displayMsg method " + Thread.currentThread().getName());
        synchronized(this){
            System.out.print("**" + msg);        
            try {
                Thread.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("*");
        }
    }
}

Output

Inside displayMsg method Thread-0
Inside displayMsg method Thread-3
Inside displayMsg method Thread-2
Inside displayMsg method Thread-1
**I*
**am*
**not*
**synchronized*

It can be seen from the output how the first print statement is executed by all the threads as that is not inside the synchronized block. After that only a single thread executes at a time and finishes its execution of the synchronized block only then another thread enters the synchronized block.

Drawback of using Synchronization in Java

Synchronization can introduce thread contention, which occurs when two or more threads try to access the same resource simultaneously and cause the Java runtime to execute one or more threads more slowly, or even suspend their execution. Thread Starvation and livelock are forms of thread contention.

That's all for this topic Synchronization in Java - Synchronized Method And Block. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Why wait(), notify() And notifyAll() Must be Called Inside a Synchronized Method or Block
  2. Inter-thread Communication Using wait, notify And notifyAll Methods
  3. Difference between ReentrantLock and Synchronized
  4. Deadlock in Java Multi-Threading
  5. ThreadLocal class in Java

You may also like-

  1. Java Multi-Threading Interview Questions
  2. varargs in Java
  3. covariant return type in Java
  4. Java pass by value or pass by reference
  5. Method reference in Java 8
  6. interface default methods in Java 8
  7. How HashMap internally works in Java
  8. Java Program to count number of words in a String

4 comments:

  1. Good collection on Java multithreading.

    ReplyDelete
  2. Why have we used "this" keyword in first example when creating thread?
    t=new Thread(new MyThread2(msg," ")); is giving stack overflow error.
    Please explain

    ReplyDelete
    Replies
    1. In the example MyClass is of type Runnable.
      "this" denotes the current object here so I am passing the current instance of MyClass (which is Runnable) to Thread class' constructor.

      Otherwise use this - new Thread(new MyClass1(msg, "I")).start(); but then comment these lines in the MyClass constructor -
      t = new Thread(this);
      t.start();

      Delete