Java

Synchronization in Java | Explained

When we begin two or more threads in the same program then there is a possibility that the multiple threads attempt to access the same resource and consequently, inconsistent results will be produced. And in order to provide reliable communication between the multiple threads, the concept of synchronization is used in java. The synchronized keyword in java synchronizes the actions of multiple threads and makes sure that only one thread can access a specific resource at a particular time.

This write-up will explore the various aspects of synchronization in java and in this regard, this article will cover the following concepts:

So, let’s get

What is Synchronization in Java?

It is a process that controls the access of more than one thread to any shared resource and hence, avoids inconsistent results.

Why is Synchronization Used?

In java, the main purpose of using synchronization is to avoid the inconsistent behavior of threads and to prevent threads interference.

Why synchronized Keyword is used in Java

Synchronized is a modifier that can be applied on the methods and blocks only and can’t be applied on variables and classes. To understand this concept

How to Use Synchronization in Java

We will consider some examples for a profound understanding. Initially, we will create a very simple java program to increment the value of the counter. Next, we will extend this example to the multithreaded scenario. Gradually, we will head toward the synchronization where we will learn why the synchronized keyword is used in java?

Example
In this example, we will create a simple program that has a variable counter and a user-defined function incrementValue().

class CounterClass {
    int counter;
   
    public void incrementValue() {
        counter++;
    }
}
public class SynchronizationExample {

    public static void main(String[] args) {
        CounterClass count = new CounterClass();
        count.incrementValue();
        System.out.println("Counter: " + count.counter);
    }

}

Whenever we invoke the incrementValue() it will increment the value of counter by 1:

Value of the counter is successfully incremented to 1 which shows the appropriateness of our program. If we call the incrementValue() method twice, then the value of counter will 2. Similarly, it will show the value of counter as 3 if we call the incrementValue() method three times as shown in the below snippet:

In the above code snippet, we invoked the incrementValue() method four times, so it shows the value of counter as 4.

Example
Now, let’s extend the above example a little bit where we will create a thread which will call the incrementValue() ten times:

class CounterClass {

    int counter;

    public void incrementValue() {
        counter++;
    }
}

public class SynchronizationExample {

    public static void main(String[] args) throws Exception {
        CounterClass count = new CounterClass();
        Thread th1 = new Thread(new Runnable() {
            public void run() {
                for (int i = 1; i <= 10; i++) {
                    count.incrementValue();
                }
            }
        });
        th1.start();
        th1.join();
        System.out.println("Counter: " + count.counter);
    }

}

In the above code-snippet join() method is used with the object of Thread class so that one thread should wait until the other thread completes the execution. The above code-snippet produces the following output:

From the output it is clear that thread calls the incrementValue() ten times and hence the value of counter is equal to ten.

So far so good, now let’s consider a multithreaded environment and create one more thread to see what will happen when two threads call for the same resource(i.e. incrementValue() method) at the same time.

Example

In this example, we have two threads both will call the incrementValue() method five hundred times:

class CounterClass {

    int counter;

    public void incrementValue() {
        counter++;
    }
}

public class SynchronizationExample {

    public static void main(String[] args) throws Exception {
        CounterClass count = new CounterClass();
        Thread th1 = new Thread(new Runnable() {
            public void run() {
                for (int i = 1; i <= 500; i++) {
                    count.incrementValue();
                }
            }
        });

        Thread th2 = new Thread(new Runnable() {
            public void run() {
                for (int i = 1; i <= 500; i++) {
                    count.incrementValue();
                }
            }
        });

        th1.start();
        th1.join();
        th2.start();
        th2.join();
        System.out.println("Counter: " + count.counter);
    }

}

As both the threads are calling the counterValue() five hundred times so, technically the value of increment should be one thousand. Let’s consider the below snippet to see what does output says:

Instead of “1000”, we get “753”, now what does that mean? Why didn’t we get the counter’s value as 1000?

Well, it is because multithreading supports parallel processing and hence, there is always a possibility that both the threads fetch the value of the counter at the same time and hence both get the same value of counter so, in such a case instead of incrementing the value of counter two times, it increments only once.

So, how to avoid such a scenario? Well! In such cases, the synchronized keyword will be used.

Example
We will use the synchronized keyword with the “incrementValue()” method as a result only one thread will access the “incrementValue()” method at one time. All the code will remain the same as in the previous example only synchronized keyword will be added with the incrementValue() method as shown in the snippet:

public synchronized void incrementValue() {
        counter++;
    }

Now if thread 1 is working with the incrementValue() method then thread 2 will wait, and vice versa. This time we will get the following output:

The above-given snippet shows the effectiveness of the “synchronized” keyword.

Conclusion

Synchronization is a process that controls the access of more than one thread and makes sure/verifies that only one thread can access the resource at a particular time. To achieve synchronization, the synchronized keyword/modifier is used, and it can be applied to the methods and blocks but can’t be applied to variables and classes. In java, the main purpose of using synchronization is to avoid the inconsistent behavior of threads and to prevent threads interference.

About the author

Anees Asghar

I am a self-motivated IT professional having more than one year of industry experience in technical writing. I am passionate about writing on the topics related to web development.