Question

Is there any general way or rules exits by which we can ensure the thread safety of static methods specifically used in various Utility classes of any applications. Here I want to specifically point out the thread safety of Web Applications.

It is well know that static methods with Immutable Objects as parameters are thread safe and Mutable Objects are not.

If I have a utility method for some manipulation of java.util.Date and that method accepts an instance of java.util.Date, then this method would not be thread safe. Then how to make it thread safe without changing the way of parameter passing?

public class DateUtils {

    public static Date getNormalizeDate(Date date) {
        // some operations
    }   
}

Also is the class javax.faces.context.FacesContext mutable? Is it thread safe to pass an instance of this class to such static utility method?

This list of classes, instances of which can be or cannot be passed as parameters, could be long; so what points should we keep in mind while writing codes of such utility classes?

Was it helpful?

Solution

It is well known that static methods with immutable objects as parameters are thread safe and mutable objects are not.

I would contest this. Arguments passed to a method are stored on a stack, which is a per-thread idiom.

If your parameter is a mutable object such as a Date then you need to ensure other threads are not modifying it at the same time elsewhere. But that's a different matter unrelated to the thread-safety of your method.

The method you posted is thread-safe. It maintains no state and operates only on its arguments.

I would strongly recommend you read Java Concurrency in Practice, or a similar book dedicated to thread safety in Java. It's a complex subject that cannot be addressed appropriately through a few StackOverflow answers.

OTHER TIPS

Since your class does not hold any member variables, your method is stateless (it only uses local variables and the argument) and therefore is thread safe.

The code that calls it might not be thread safe but that's another discussion. For example, Date not being thread safe, if the calling code reads a Date that has been written by another thread, you must use proper synchronization in the Date writing and reading code.

Given the structure of the JVM, local variables, method parameters, and return values are inherently "thread-safe." But instance variables and class variables will only be thread-safe if you design your class appropriately. more here

I see a lot of answers but none really pointing out the reason.

So this can be thought like this, Whenever a thread is created, it is created with its own stack (I guess the size of the stack at the time of creation is ~2MB). So any execution that happens actually happens within the context of this thread stack. Any variable that is created lives in the heap but it's reference lives in the stack with the exceptions being static variables which do not live in the thread stack.

Any function call you make is actually pushed onto the thread stack, be it static or non-static. Since the complete method was pushed onto the stack, any variable creation that takes place lives within the stack (again exceptions being static variables) and only accessible to one thread.

So all the methods are thread safe until they change the state of some static variable.

I would recommend creating a copy of that (mutable) object as soon as the method starts and use the copy instead of original parameter.

Something like this

public static Date getNormalizeDate(Date date) {
    Date input = new Date(date.getTime());
    // ...
}

Here's how I think of it: imagine a CampSite (that's a static method). As a camper, I can bring in a bunch of objects in my rucksack (that's arguments passed in on the stack). The CampSite provides me with a place to put my tent and my campstove, etc, but if the only thing the CampSite does is allow me to modify my own objects then it's threadsafe. The CampSite can even create things out of thin air (FirePit firepit = new FirePit();), which also get created on the stack.

At any time I can disappear with all my objects in my ruckstack and one of any other campers can appear, doing exactly what they were doing the last time they disappeared. Different threads in this CampSite will not have access to objects on the stack created CampSite in other threads.

Say there's only one campStove (a single object of CampStove, not separate instantiations). If by some stretch of the imagination I am sharing a CampStove object then there are multi-threading considerations. I don't want to turn on my campStove, disappear and then reappear after some other camper has turned it off - I would forever be checking if my hot dog was done and it never would be. You would have to put some synchronization somewhere... in the CampStove class, in the method that was calling the CampSite, or in the CampSite itself... but like Duncan Jones says, "that's a different matter".

Note that even if we were camping in separate instantiations of non-static CampSite objects, sharing a campStove would have the same multi-threading considerations.

We will take some examples to see if static method is Thread-Safe or not.

Example 1:

public static String concat (String st1, String str2) {
return str1 + str2
}

Now above method is Thread Safe.

Now we will see another example which is not thread-safe.

Example 2:

 public static void concat(StringBuilder result, StringBuilder sb, StringBuilder sb1) {
    result.append(sb);
    result.append(sb1);
    }

If you see both methods are very very primitive but still one is thread safe and other one is not. Why? What difference both having?

Are static methods in utilities prone to non thread-safe? Lot’s of questions right?

Now every thing depends on how you implement method & which type of objects you are using in your method. Are you using thread safe objects? Are these objects / classes are mutable?

If you see in Example 1 arguments of concat method are of type String which are immutable and passed by value so this method is completely thread-safe.

Now in Example 2 arguments are of StringBuilder type which are mutable so other thread can change value of StringBuilder which makes this method is potentially non thread-safe.

Again this is not completely true. If you are calling this utility method with local variables then you never having any problem related to thread-safety. Because each thread uses it’s own copy for local variables so you never run into any thread safety issues. But that is beyond scope of above static method. It’s depend on calling function / program.

Now static methods in utility class are kind of normal practice. So how we can avoid it? If you see Example 2 I am modifying 1st parameter. Now if you want to make this method really thread safe then one simple thing you can do. Either use non-mutable variables / objects or do not change / modify any method parameters.

In Example 2 we already used StringBuilder which is mutable so you can change implementation to make static method thread safe as follows:

public static String concat1(StringBuilder sb, StringBuilder sb1) {
StringBuilder result = new StringBuilder();
result.append(sb);
result.append(sb1);
return result.toString();
}

Again going to basics always remember if you are using immutable objects & local variables then you are miles away from thread safety issues.

From the arcticle(https://nikhilsidhaye.wordpress.com/2016/07/29/is-static-method-in-util-class-threadsafe/)Thank you Nikhil Sidhaye for this simple article

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top