Skip to main content

Threads in Java - Synchronization (Part 8)

We have seen in our previous posts, in a typical Java application, multiple threads run in parallel to complete program execution. This may lead to a situation where multiple threads try to access the same resource simultaneously. This can produce unforeseen and erroneous results.

Therefore, a mechanism is required which ensures only one thread can access a resource at a given point of time. Java has the concept synchronization for this mechanism. This allows the programmer to synchronize tasks using synchronized blocks/methods.

  • Synchronized blocks are marked with the keyword "synchronized".
  • A synchronized block is synchronized on some object. This ensures mutually exclusive access to the shared resource and prevents data race.
  • Only one thread can execute inside a synchronized block at a time. All other threads attempting to enter the synchronized block are blocked until the thread inside the block exits the block.
  • Synchronization also prevents reordering of the code statements by the compiler.
  • Before entering a synchronized block, a thread needs to acquire the lock, at this point it reads data from main memory than cache and when it releases the lock, it flushes write operation into main memory which eliminates memory inconsistency errors.
Synchronization is implemented with a concept called monitors. Only one thread can own a monitor at a given time. 
When a thread acquires a lock, it is said to have entered the monitor. All other threads attempting to enter the locked monitor will be suspended until the first thread exits the monitor.

Monitor

A monitor allows threads to have both mutual exclusion and ability to block (wait) for a certain condition to become true. It is also called intrinsic lock. A monitor can also signal other threads that a condition has been met. It has both a lock and wait set. Any object can serve as a monitor.

In JVM, every class and object is logically associated with a monitor. To implement mutual exclusion capability of monitors, a lock (also called mutex) is associated with each object and class. This is called semaphore in OS terms.

If one thread owns a lock on some data, no other thread can access it until the lock is released. It is a good idea to say that each object has a monitor since each object can have its own critical section and it is capable of monitoring the thread sequence.

There are two ways to gain access to object monitor - 
  1. Add the synchronized keyword to the method
          public synchronized int method(){
               ...
         }
  • Add the synchronized block
            public int method(){
                synchronized(someObject){
                  ...
               }
            }

Static vs non-static synchronized methods

From the previous discussion, we know that synchronized is an implementation of the Monitor.
Object x = new Object();
Object y = new Object();
...
synchronized(x){
    A();
}
...
synchronized(y){
    B();
}
...
synchronized(c){
    C();
}
A thread running C() would block another thread from entering the block of code protecting A() as they are synchronized on the object x. However, a thread could enter the block of code protecting B() as it is synchronized on object y.

When we use the synchronized modifier on an instance method (non-static), it is very similar to having a synchronized block with "this" as the argument. 
public synchronized void A() {
  doStuff();
}
...
public void B() {
    synchronized(this) {
        doStuff();
    }
}
Both A() and B() will behave in the same way. 

If we have a static method with the synchronized modifier, it is very similar to having a synchronized block with ClassName.class as the argument. 
class MyClass {
  public void static synchronized A() {
    doStaticStuff();
  }
  public static void B() {
    synchronized(MyClass.class) {
      doStaticStuff();
    }
  }
  public void C() {
    synchronized(this.getClass()) {
      doStuff();
    }
  }
}
In the above code, A() and B() will behave in the same way. An executing thread will also be blocked from accessing the code in C() as it is synchronizing on the same object. (source)

Code example

Following code shows the concepts in action - 
The output of the above program will be same every time we run the program -

Output

Sending Hello World!
Hello World! sent

Sending Bye World!
Bye World! sent

Conclusion

Congratulations!! 🙋 today we discussed the concepts of synchronization, monitor, static and non-static synchronization with their implementations. I hope you enjoyed this post.

You can find the complete code of this project on my GitHub in this commit. Feel free to fork or open issues, if any.

I would love to hear your thoughts on this and would like have suggestions from you to make it better. 

Feel free to befriend me on FacebookTwitter or Linked In or say Hi by email.

Happy Coding 😊

Comments

Popular posts from this blog

Threads in Java - Masterclass (Part 0)

Multithreading is a way to introduce concurrency in a program. In any case, if there are parallel paths in our program (parts which do not depend on the result from another part), we can make use of multithreading.
One should exploit this feature, especially with all these multiple core machines nowadays.

Below are a few reasons why we should use multithreading -
1. Keep a process responsive There was once a time when you would print a document in MS Word and the application would freeze for an annoyingly long amount of time until the job finished. Eventually, Microsoft solved this problem by running a printing job parallel to the main thread/ GUI thread.  To be clear though, not only GUI apps but Network services have to keep an ear to the ground for new clients, dropped connections and cancellation requests. In either case, it is critical to do the heavy lifting on a secondary thread to keep the user satisfied. 2. Keep a processor busy Keeping a processor busy can be a tough task e…

Parsing XML using Retrofit

Developing our own type-safe HTTP library to interface with a REST API can be a real pain as we have to handle many aspects -
making connectionscachingretrying failed requeststhreadingresponse parsingerror handling, and more.  Retrofit, on the other hand, is a well-planned, documented and tested library that will save you a lot of precious time and headaches. In this tutorial, we are going to discuss how we can parse the XML response returned from https://timesofindia.indiatimes.com/rssfeedstopstories.cms using the Retrofit library.

To work with Retrofit, we need three classes -  Model class to map the JSON dataInterfaces which defines the possible HTTP operationsRetrofit.Builder class - Instance which uses the interface and the Builder API which allows defining the URL endpoint for the HTTP operation. Every method of the above interface represents on possible API call. The request type is specified by using appropriate annotations (GET, POST). The response is returned as a Call object…

Material design profile page in Android

Hey everyone, some days back I was working on one my personal Android project. In that project, I was supposed to create a simple profile page for a user. This profile page was supposed to show some basic details of a user.

The output of this UI will be like this -
I created the profile page using material design and in this post, I am going to discuss a step by step tutorial to create a simple yet elegant profile page. Without further ado, let's get started.
Creating a new project Click on File ➤ New Project ➤ Empty Activity and fill the necessary details. Change styles.xml fileNavigate to app\src\main\res\values\styles.xmlChange the style value from DarkActionBar to NoActionBar as below<resources><!-- Base application theme. --><stylename="AppTheme"parent="Theme.AppCompat.Light.NoActionBar"><!-- Customize your theme here. --><itemname="colorPrimary">@color/colorPrimary</item><itemname="colorPrimaryDark&qu…