Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / programming / threads

Threading in Java : A Look at Synchronized

5.00/5 (1 vote)
19 Jun 2021CPOL2 min read 4.7K  
Meaning of synchronized keyword with a deeper look
This article tries to explain the meaning of keyword synchronized w.r.t. object as well as class level lock. The purpose of the exercise done in this article is to understand that a synchronized function internally uses an object level lock while a static synchronized function internally uses a class level lock for its entire code.

Introduction

Some wise men have said "Never judge people on their Face value. A lot is hidden in their subconscious mind". Does this hold true for synchronized functions? Let's see. Take the following program:

Java
locks.java
-----------
class processor implements Runnable{	
    public void run() {
        display(); 
    }
    public void display() {
            synchronized (processor.lock){
	        for (int i = 0 ; i<= 5; i++) {
                System.out.println("i = " + i + " In thread2" + Thread.currentThread() );
            }		   
        }
    }
} 

class locks {
    public static void main(String[] args) {
        processor p1 = new processor();
		processor p2 = new processor();
        Thread t1 = new Thread(p1, "t1");
        Thread t2 = new Thread(p2, "t2");
		
        t1.start();
        t2.start();		
    }
}

Output
=======
i = 0 In thread2Thread[t1,5,main]
i = 1 In thread2Thread[t1,5,main]
i = 2 In thread2Thread[t1,5,main]
i = 3 In thread2Thread[t1,5,main]
i = 4 In thread2Thread[t1,5,main]
i = 5 In thread2Thread[t1,5,main]
i = 0 In thread2Thread[t2,5,main]
i = 1 In thread2Thread[t2,5,main]
i = 2 In thread2Thread[t2,5,main]
i = 3 In thread2Thread[t2,5,main]
i = 4 In thread2Thread[t2,5,main]
i = 5 In thread2Thread[t2,5,main]

The above program compiles and runs successfully to produce a desired synchronized output. This needs no explanation. The threads t1 and t2 are synchronized using a Class level lock "processor.lock" such that the for loop in the display() function is executed by one and only one thread created out of any object of the processor class.

Now take the similar program with a slightly different look.

Java
locks.java
----------
class processor implements Runnable{	
    public void run() {
        display(); 
    }
    // Observe the synchronized statement below 
    public static synchronized void display() {
	    for (int i = 0 ; i<= 5; i++) {
            System.out.println("i = " + i + " In thread2" + Thread.currentThread() );
        }		   
    }
} 

class locks {
    public static void main(String[] args) {
        processor p1 = new processor();
		processor p2 = new processor();
        Thread t1 = new Thread(p1, "t1");
        Thread t2 = new Thread(p2, "t2");
		
        t1.start();
        t2.start();		
    }
}

Output
=======
i = 0 In thread2Thread[t1,5,main]
i = 1 In thread2Thread[t1,5,main]
i = 2 In thread2Thread[t1,5,main]
i = 3 In thread2Thread[t1,5,main]
i = 4 In thread2Thread[t1,5,main]
i = 5 In thread2Thread[t1,5,main]
i = 0 In thread2Thread[t2,5,main]
i = 1 In thread2Thread[t2,5,main]
i = 2 In thread2Thread[t2,5,main]
i = 3 In thread2Thread[t2,5,main]
i = 4 In thread2Thread[t2,5,main]
i = 5 In thread2Thread[t2,5,main]

The above program compiles and runs successfully to produce a desired output exactly similar to the earlier program. Well, the only change here is that we have declared display as a static synchronized function(). We get a similar output exactly like the earlier program.

Java
public static synchronized void display() {
    ....
    .... 
    ....
}

EXACTLY EQUALS

public void display() {
    synchronized(process.lock) {
        ....
        ....
        ....
        ....
    }
}

And NOT EQUAL TO

public void display() {
    ......
    ......
    ......
    synchronized(process.lock){
        ....
        ....
        ....
    }
}

Thus when you see a function declared as static synchronized, it means the code within it is guarded by a class level lock.

Now let's move on to object locks. Take the following program:

Java
locks.java
-----------
class processor implements Runnable{	
    public void run() {
        display(); 
    }
    public void display() {
            synchronized (this){
	        for (int i = 0 ; i<= 5; i++) {
                System.out.println("i = " + i + " In thread2" + Thread.currentThread() );
            }		   
        }
    }
} 

class locks {
    public static void main(String[] args) {
        processor p1 = new processor();
		processor p2 = new processor();
        Thread t1 = new Thread(p1, "t1");
        Thread t2 = new Thread(p1, "t2");
		
        t1.start();
        t2.start();
		
    }
}

Output
=======
i = 0 In thread2Thread[t1,5,main]
i = 1 In thread2Thread[t1,5,main]
i = 2 In thread2Thread[t1,5,main]
i = 3 In thread2Thread[t1,5,main]
i = 4 In thread2Thread[t1,5,main]
i = 5 In thread2Thread[t1,5,main]
i = 0 In thread2Thread[t2,5,main]
i = 1 In thread2Thread[t2,5,main]
i = 2 In thread2Thread[t2,5,main]
i = 3 In thread2Thread[t2,5,main]
i = 4 In thread2Thread[t2,5,main]
i = 5 In thread2Thread[t2,5,main]

The above program compiles and runs successfully to produce a desired synchronized output. This needs no explanation. The threads t1 and t2 are synchronized using an object level lock "this" such that the for loop in the display() function is executed by one and only one thread created out of one and only one object of the processor class.

Now take the similar program with a slightly different look.

Java
locks.java
----------
class processor implements Runnable{	
    public void run() {
        display(); 
    }
    // Observe the synchronized statement below 
    public synchronized void display() {
	    for (int i = 0 ; i<= 5; i++) {
            System.out.println("i = " + i + " In thread2" + Thread.currentThread() );
        }		   
    }
} 

class locks {
    public static void main(String[] args) {
        processor p1 = new processor();
		processor p2 = new processor();
        Thread t1 = new Thread(p1, "t1");
        Thread t2 = new Thread(p1, "t2");
		
        t1.start();
        t2.start();		
    }
}

Output
=======
i = 0 In thread2Thread[t1,5,main]
i = 1 In thread2Thread[t1,5,main]
i = 2 In thread2Thread[t1,5,main]
i = 3 In thread2Thread[t1,5,main]
i = 4 In thread2Thread[t1,5,main]
i = 5 In thread2Thread[t1,5,main]
i = 0 In thread2Thread[t2,5,main]
i = 1 In thread2Thread[t2,5,main]
i = 2 In thread2Thread[t2,5,main]
i = 3 In thread2Thread[t2,5,main]
i = 4 In thread2Thread[t2,5,main]
i = 5 In thread2Thread[t2,5,main]

The above program compiles and runs successfully to produce a desired output exactly similar to the earlier program. Well, the only change here is that we have declared display as a synchronized function(). We get a similar output exactly like the earlier program.

Java
public synchronized void display() {
    ....
    .... 
    ....
}

EXACTLY EQUALS

public void display() {
    synchronized(this) {
        ....
        ....
        ....
        ....
    }
}

And NOT EQUAL TO

public void display() {
    ......
    ......
    ......
    synchronized(this){
        ....
        ....
        ....
    }
}

Thus when you see a function declared as synchronized, it means the code within it is guarded by a object level lock.

The purpose of this exercise was to understand that a synchronized function internally uses an object level lock while a static synchronized function internally uses a class level lock for its entire code. Well, indeed a lot is hidden behind the subconscious mind of the keyword synchronized in Java. What say?

Points of Interest

Static synchronized when applied to a method refers to class level lock while mere synchronized when applied to a method refers to object level lock.

Readers, please feel free to leave a comment whether you feel this article was helpful for you. This makes me understand if i need to add some more things as a part of explaination. Your feedback is most welcome. Thanks!

History

  • 19th June, 2021: Initial revision

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)