Understanding Java Synchronized Keyword

Synchronization
0 95

Get real time updates directly on you device, subscribe now.

3 min read

In a multi-threaded environment, there is always a race between two or more threads attempting to update the mutable shared data at the same time. Java has offered a mechanism where we can avoid these race conditions. The mechanism is basically the synchronization of threads which are accessing the shared data. To achieve this, we mark a piece of logic or code block with java synchronized keyword, thus allowing only one thread to execute at any given time.

Java Synchronized Keyword

The synchronized keyword can be used on three different levels:

  • Instance methods
  • Static methods
  • Code blocks

To provide synchronization, Java internally uses a monitor which is also known as monitor lock or intrinsic lock. These monitors are bound to an object, thus all synchronized blocks of the same object can have only one thread executing them at the same time. In a more simpler terms, we can say that a thread that needs exclusive and consistent access to an object’s fields has to acquire the object’s monitor (intrinsic lock) before accessing them, and then release the intrinsic lock when it’s done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.

Synchronized Instance Method

To make a method synchronized, simply add the synchronized keyword to its declaration:

public class SynchronizedCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }
}

If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:

  • First, when one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
  • Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
Constructors cannot be synchronized — using the synchronized keyword with a constructor is a syntax error.

Synchronized Static Methods

Static methods are synchronized just like instance methods

public class SynchronizedCounter {
    private int c = 0;

    public static synchronized void increment() {
        c++;
    }

    public static synchronized void decrement() {
        c--;
    }

    public static synchronized int value() {
        return c;
    }
}

When a static synchronized method is invoked, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class’s static fields is controlled by a lock that’s distinct from the lock for any instance of the class.

Synchronized Code Blocks

Sometimes the situations demand not to synchronize the entire method but only some instructions within it. This can be achieved by applying synchronized to that particular code block:

public class SynchronizedCodeBlock {

    public void addName(String name) {
      synchronized(this) {
        lastName = name;
        nameCount++;
      }
      nameList.add(name);
    }

}

In the above example, the method addName synchronizes the changes to lastName and nameCount and avoid synchronizing invocations of other objects’ methods.

Conclusion

In this quick journal entry, we have seen different ways of using the synchronized keyword to achieve thread synchronization and handle the race condition between multiple threads.