Core Java

Java Synchronized Keyword Example

In this example, we shall show you how to use the Java synchronized keyword and achieve synchronization in java.

1. What is Synchronized Keyword in Java?

Java allows us to use concurrency and multithreading pretty easily. Some of the most common use cases are those in which we have an object and many threads interacting with it. This can create many problems, because in cases that 2 different threads try to interact with the same resource, we have no idea what may actually happen (which is something that needs to be avoided in programming).

This is why Java provides the synchronized keyword, which allows us to handle certain parts of code in an atomic way. Essentially, this means that when there are more than one threads that need to access a synchronized part of code, (increment a counter, add objects in a list, etc) there is no way that one thread will interrupt another thread, so we are perfectly sure that everything will work as intended.

2. How to use the Java Synchronized Keyword

There are two ways to use the synchronized keyword to achieve synchronization in java. It can either be set in a method of a class, or in part of code inside a method, which becomes a synchronized block. In both cases, code inside a synchronized method or block is only accessed by one thread at a time.

Below, we present you both ways to use the synchronized keyword.

2.1 Synchronized Method

The SynchronizedMethodClass.java class below has one method, syncMethod(String threadName), stated with the synchronized keyword.

SynchronizedMethodClass.java

import java.util.ArrayList;

public class SynchronizedMethodClass {
    private ArrayList<Integer> nums1;
    private String pos1;

    public SynchronizedMethodClass() {
        nums1 = new ArrayList<Integer>();
        nums1.add(0);
        pos1 = "0";
    }

    public ArrayList<Integer> getNums1() {
        return nums1;
    }

    public void setNums1(ArrayList<Integer> nums1) {
        this.nums1 = nums1;
    }

    public String getPos1() {
        return pos1;
    }

    public void setPos1(String pos1) {
        this.pos1 = pos1;
    }

    public synchronized void syncMethod(String threadName) {
        Integer number = nums1.get(nums1.size() - 1) + 1;
        pos1 = String.valueOf(number);
        nums1.add(number);
        System.out.println("Thread " + threadName + " : "
                + nums1.get(nums1.size() - 1) + " - " + pos1);
    }
}

The SyncMethodRunnable.java class below is an implementation of the Runnable interface that will invoke the synchronized method of its SynchronizedMethodClass field, when started.

SyncMethodRunnable.java

public class SyncMethodRunnable implements Runnable {

    private SynchronizedMethodClass synchronizedMethodClass;

    private String threadName;

    public SyncMethodRunnable(SynchronizedMethodClass synchronizedMethodClass, String threadName) {
        this.synchronizedMethodClass = synchronizedMethodClass;
        this.threadName = threadName;
    }

    public void run() {
        for (int i = 0; i < 5; i++) {
            synchronizedMethodClass.syncMethod(threadName);
        }
    }

}

In order to run the example, we create two Threads to run two instances of the SyncMethodRunnable. Both threads use the same instance of the SynchronizedMethodClass class. So both threads will invoke the synchronized method of the SynchronizedMethodClass object.
we do it AppForSynchronizedMethod.java class.

AppForSynchronizedMethod.java

public class AppForSynchronizedMethod {
    public static void main(String[] args) throws InterruptedException {

        SynchronizedMethodClass example1 = new SynchronizedMethodClass();

        System.out.println("**** Running AppForSynchronizedMethod.java *****");
        System.out.println("**** Synchronized Method example*****");

        Thread thread1 = new Thread(new SyncMethodRunnable(example1, "1"));
        Thread thread2 = new Thread(new SyncMethodRunnable(example1, "2"));

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println("List 1 is: " + example1.getNums1()
                + " /Position 1: " + example1.getPos1()
                + "\n");
    }
}

As a result, both threads start, but the first one to invoke the synchronized method of the SynchronizedMethodClass object is Thread 1, and when it finishes Thread 2 manages to invoke the method. Since they both use the same instance of the SynchronizedMethodClass class, the list is finally filled with 10 numbers and the position is set to 10.

Output of AppForSynchronizedMethod.java class is shown in Fig. 1 below.

Java Synchronized - Output of AppForSynchronizedMethod.java
Fig. 1 . Output of AppForSynchronizedMethod.java

2.2 Synchronized Block

The SynchronizedBlockClass.java class below has one method, inside which the synchronized keyword is set. The synchronized block created takes a parameter, which is the instance of the SynchronizedBlockClass.java class. This parameter may be one attribute of the class, or the whole class object, according to the needs of the programmer. Since the whole instance of the class is set as the parameter in the synchronized block, it is now locked against changes until the thread finishes code execution in the block. The rest part of the method that is not inside the block may be accessed simultaneously by all threads that invoke the method.

SynchronizedBlockClass.java

import java.util.ArrayList;

public class SynchronizedBlockClass {

    private ArrayList<Integer> nums2;
    private String pos2;
    private int counter;

    public SynchronizedBlockClass() {
        nums2 = new ArrayList<Integer>();
        nums2.add(0);
        pos2 = "0";
    }

    public ArrayList<Integer> getNums2() {
        return nums2;
    }

    public void setNums2(ArrayList<Integer> nums2) {
        this.nums2 = nums2;
    }

    public String getPos2() {
        return pos2;
    }

    public void setPos2(String pos2) {
        this.pos2 = pos2;
    }

    public int getCounter() {
        return counter;
    }

    public void setCounter(int counter) {
        this.counter = counter;
    }

    public void syncBlock(String threadName) {
        counter++;
        System.out.println("Thread " + threadName + " - counter: " + counter);
        synchronized (this) {
            Integer number = nums2.get(nums2.size() - 1) + 1;
            pos2 = String.valueOf(number);
            nums2.add(number);
            System.out.println("Thread " + threadName + " Added to list: "
                    + nums2.get(nums2.size() - 1) + " - " + pos2);
        }
    }

}

The SyncBlockRunnable.java class below is an implementation of the Runnable interface that will invoke the synchronized method of its SynchronizedBlockClass field, when started.

SynchronizedBlockRunnabled.java

public class SyncBlockRunnable implements Runnable {

    private SynchronizedBlockClass synchronizedBlockClass;

    private String threadName;

    public SyncBlockRunnable(SynchronizedBlockClass synchronizedBlockClass, String threadName) {
        this.synchronizedBlockClass = synchronizedBlockClass;
        this.threadName = threadName;
    }
    public void run() {
        for (int i = 0; i < 5; i++) {
            synchronizedBlockClass.syncBlock(threadName);
        }
    }
}

Now in AppForSynchronizedBlock.java class, we create two Threads to run two instances of the SyncBlockRunnable. Both threads use the same instance of the SynchronizedBlockClass class. So both threads will invoke its method, but only one of them will get in the synchronized block of the method at a time.

AppForSynchronizedBlock.java

public class AppForSynchronizedBlock {

    public static void main(String[] args) throws InterruptedException {

        SynchronizedBlockClass example2 = new SynchronizedBlockClass();
        System.out.println("**** Running AppForSynchronizedBlock.java *****");
        System.out.println("**** Synchronized Block example*****");

        Thread syncMethodThread1 = new Thread(new SyncBlockRunnable(example2, "1"));
        Thread syncMethodThread2 = new Thread(new SyncBlockRunnable(example2, "2"));

        syncMethodThread1.start();
        syncMethodThread2.start();

        syncMethodThread1.join();
        syncMethodThread2.join();

        System.out.println("List 2 is: " + example2.getNums2()
                + " /Position 2: " + example2.getPos2()
                + " / counter : " + example2.getCounter());

    }
}

As a result, both threads invoke the method of the SynchronizedBlockClass object. But only one thread at a time locks the object to run the synchronized block. The counter increment is out of the synchronized block, so the counter result is wrong. But the rest of the method that is inside the synchronized block is protected against being invoked by many threads simultaneously and achieve synchronization in java, so the list and position result is correct.

Output of AppForSynchronizedBlock.java class is shown in Fig. 2 below.

Java Synchronized - Output of AppForSynchronizedBlock.java
Fig. 2 Output of AppForSynchronizedBlock.java

3. Download the Source Code

Download
You can download the full source code of synchronized example here : Java Synchronized Keyword Example

Last updated on Aug 23, 2019

Abhinav Nath Gupta

Abhinav holds a Master degree in Computer Science and Engineering from the National Institute of Technology Karnataka. He has finished his graduation from Information Technology Department in the Anand Engineering College, Agra. During his studies he has been involved with a large number of projects ranging from Networking and Cryptography. He works as a software development engineer at a software development firm in bengaluru where he is mainly involved with projects based on Nodejs. He is interested in cryptography, data security, cryptocurrency and cloud computing, and published articles regarding these topics. He can be reached at abhi.aec89@gmail.com.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button