Friday, September 15, 2023

Avoid Mixing static and non static synchronized method - Java mistake 2 Example

Using a static and non-static synchronized method for protecting shared resources is another Java mistake we are going to discuss in this part of our series “learning from mistakes in Java”. In the last article, we have seen why double and float should not be used for monetary calculation, In this tutorial, we will find out why using static and non-static synchronized methods together for protecting the same shared resource is not advisable.  I have seen some times Java programmers mix static synchronized method and instance synchronized method to protect the same shared resource.

They either don't know or failed to realize that static synchronized and non-static synchronized methods lock on two different objects which breaks the purpose of synchronizing shared resources as two threads can concurrently execute these two methods breaking mutual exclusive access, which can corrupt the status of a mutable object or even cause subtle race condition in Java or even more horrible deadlock in java.




Static and non-static synchronized method Java

static and non static synchronized method in javaFor those who are not familiar static synchronized method locked on class object e.g. for string class, it's String.class while instance synchronized method locks on the current instance of Object denoted by “this” keyword in Java

Since both of these objects are different they have a different lock so while one thread is executing the static synchronized method, the other thread in java doesn’t need to wait for that thread to return instead it will acquire a separate lock denoted byte .class literal and enter into the static synchronized method. 

This is even a popular multi-threading interview question where the interviewer asked on which lock a particular method gets locked, sometimes also appears in Java test papers.

The bottom line is that never mix static and non-static synchronized methods for protecting the same resource.

And, if you are serious about mastering Java multi-threading and concurrency then I also suggest you take a look at these advanced Java Multithreading Courses. It's an advanced course to become an expert in Multithreading, concurrency, and Parallel programming in Java with a strong emphasis on high performance



Example of Mixing instance and static synchronized methods

Here is an example of multithreading code which is using a static and non-static synchronized method to protect the same shared resource:

public class SynchornizationMistakes {
    private static int count = 0;
 
    //locking on this object lock
    public synchronized int getCount(){
        return count;
    }
 
    //locking on .class object lock
    public static synchronized void increment(){
        count++;
    }
   
}

here shared count is not accessed in a mutually exclusive fashion which may result in passing incorrect count to the caller of getCount() while another thread is incrementing count using static increment() method.

That’s all on this part of learning from mistakes in Java. Now we know that static and non-static synchronized methods are locked on different locks and should not be used to protect the same shared object.


Other Java thread tutorials you may like:

And lastly,  Have you made any mistake in Java? If yes, let us know and what did you learned from it. I have made several mistakes but I also learned a lot from them. 

4 comments :

Anonymous said...

I think one of the main difference between synchronized method and static synchronized method is locking, former is locked on this object while later is locked on Class.class literal object. There can be only one class lock in case of static synchronized method but there can be multiple lock on synchronized method. Only one thread can execute static synchronized method at a time because its on class level.

Anonymous said...

So, I see what is wrong (two different versions of locking), but what is the best way of going about fixing this? Would this be the optimal solution:

public int getCount(){
synchronize(*.class) {
return count;
}
return count;
}

Anonymous said...

Can you clear me concept? How can you say it's java mistake? may be it could be feature that... t1.obj t2.obj can are synchronized... but t3 could be not... suppose t3 want to check modification/value of one field each neno sec then?

Inderjeet said...

In case of non static synchronized method lock will be acquired by the object(this) and in case of static synchronized lock will be acquired by class.

Post a Comment