# "synchronized" keyword in Java

In 
Published 2022-12-03

This tutorial explains the usage of "synchronized" keyword in static methods.

In my example, I start from a simple Spring Boot application created using Spring initializr.

Let's take a look at the following example.

Example #1 - "synchronized" keyword in static methods

I will create 2 thread types:

MyThreadAdd.java
package com.exampe.java;

public class MyThreadAdd extends Thread {

    Integer threadNumber;

    public MyThreadAdd(Integer threadNumber) {
        this.threadNumber = threadNumber;
    }

    public void run()
    {
        System.out.println("Thread " + this.threadNumber + " is running...");

        for (int i = 1; i <= 5; i++) {
            try {
                MyStaticCounter.add(1, this.threadNumber);
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };
        System.out.println("Thread " + this.threadNumber + " stopped.");
    }
}
MyThreadSubtract.java
package com.exampe.java;

public class MyThreadSubtract extends Thread {

    Integer threadNumber;

    public MyThreadSubtract(Integer threadNumber) {
        this.threadNumber = threadNumber;
    }

    public void run()
    {
        System.out.println("Thread " + this.threadNumber + " is running...");

        for (int i = 1; i <= 5; i++) {
            try {
                MyStaticCounter.subtract(1, this.threadNumber);
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };
        System.out.println("Thread " + this.threadNumber + " stopped.");
    }
}

I will create a class which keeps the counter and which must be accessed by ONLY a thread at a time.

package com.exampe.java;

import org.springframework.stereotype.Component;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class MyStaticCounter {

    static int counter = 0;

    // Will lock the unique MyStaticCounter instance
    public static synchronized void add(Integer value, Integer threadNumber) throws InterruptedException {
        counter = counter + value;

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("mm.ss");
        LocalTime today = LocalTime.now();
        String timeString = today.format(formatter);
        System.out.println("Time:"+timeString+"/ Thread #" + threadNumber + " /add/  Counter="+counter);

        Thread.sleep(2000);
    }

    // Will lock the unique MyStaticCounter instance
    public static synchronized void subtract(Integer value, Integer threadNumber)throws InterruptedException {
        counter = counter - value;

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("mm.ss");
        LocalTime today = LocalTime.now();
        String timeString = today.format(formatter);
        System.out.println("Time:"+timeString+"/ Thread #" + threadNumber + " /subtract/  Counter="+counter);

        Thread.sleep(2000);
    }
    
//    // Will lock only the subtract2. This is not a good approach : when we are working with more instances it is not working well !!!
//    public synchronized void subtract2(int value){
//        counter = counter - value;
//    }
}

Here is my main class :

package com.exampe.java;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

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

    SpringApplication.run(DemoApplication.class, args);

    System.out.println("--------------------------------------------");

    MyThreadAdd t1 = new MyThreadAdd(1);
    MyThreadSubtract t2 = new MyThreadSubtract(2);
    MyThreadAdd t3 = new MyThreadAdd(3);
    MyThreadSubtract t4 = new MyThreadSubtract(4);

    t1.start();t2.start();t3.start();t4.start();

    // Waiting for the threads to complete
    t1.join(); t2.join(); t3.join();t4.join();
    System.out.println("--------------------------------------------");
    System.out.println("End of the execution");
  }
}

When I run the code I get (is generally different at each run):

--------------------------------------------
Thread 3 is running...
Thread 1 is running...
Thread 2 is running...
Thread 4 is running...
Time:44.38/ Thread #3 /add/  Counter=1
Time:44.40/ Thread #1 /add/  Counter=2
Time:44.42/ Thread #4 /subtract/  Counter=1
Time:44.44/ Thread #2 /subtract/  Counter=0
Time:44.46/ Thread #4 /subtract/  Counter=-1
Time:44.48/ Thread #1 /add/  Counter=0
Time:44.50/ Thread #3 /add/  Counter=1
Time:44.52/ Thread #1 /add/  Counter=2
Time:44.54/ Thread #4 /subtract/  Counter=1
Time:44.56/ Thread #2 /subtract/  Counter=0
Time:44.58/ Thread #4 /subtract/  Counter=-1
Time:45.00/ Thread #1 /add/  Counter=0
Time:45.02/ Thread #3 /add/  Counter=1
Time:45.04/ Thread #1 /add/  Counter=2
Time:45.06/ Thread #4 /subtract/  Counter=1
Thread 1 stopped.
Time:45.08/ Thread #2 /subtract/  Counter=0
Thread 4 stopped.
Time:45.10/ Thread #3 /add/  Counter=1
Time:45.12/ Thread #2 /subtract/  Counter=0
Time:45.14/ Thread #3 /add/  Counter=1
Time:45.16/ Thread #2 /subtract/  Counter=0
Thread 3 stopped.
Thread 2 stopped.
--------------------------------------------
End of the execution

Take a look at the following new examples:

Example #2 - lock an object/variable in the class

[some code here]
synchronized(object) {
    //some code here
        
}
[some code here]

In this case, when a thread execute this synchronized block, no other thread can have access to that object, which generally is a class variable.

Example #3 - lock a method from an instance of class

public synchronized void add() {
    // Code here ...
}

In this case, when a thread execute add() method, no other thread can have access to this method, but, for the same instance of the class.