Unexpected static member behavior in multithreading

I solved the problem of random multithreading. I am happy because it works, but I would like to know why. The faulty member in the code below is called INPUT_SDF

. I thought the static end members didn't need a synchronized block, but when I remove it, things go wrong.

public class A implements Comparable<A>
{

    public static final SimpleDateFormat INPUT_SDF  = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss", Locale.US);

    ...

    public void setDate(String string) throws ParseException
    {
        synchronized (INPUT_SDF)
        {
            date = INPUT_SDF.parse(string);
        }
    }

}

      

Is my understanding of static end members wrong? Or is there something else in my code and not streamed?

+3


source to share


3 answers


Field creation static final

only makes reference streams; it does not synchronize access to the specified object.

Since SimpleDateFormat instances are not thread safe, if the instance is shared by multiple threads at the same time, you must synchronize access with it (as you do).

Creating a field static final

ensures that all threads see the same value for the link.




However, your current code is a potential bottleneck as all threads must queue to use the instance, which can lead to worse performance than just creating a new one every time.

If you want to safely reuse SimpleDateFormat instances, consider using ThreadLocal

conveniently a separate instance for each thread that will allow you to remove synchronization:

private static final ThreadLocal<SimpleDateFormat> formats =
    new ThreadLocal<SimpleDateFormat>() {
        @Override protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss", Locale.US);
        }
    };

public void setDate(String string) throws ParseException {
    return formats.get().parse(string);
}

      

+2


source


There is no way to create a static field final to make the code flow safe. It only makes the binding of the object stream reference safe and thus ensures that other threads see the same object reference in this field. It does not mutate the data stored in the object that was stored in the field (after assignment) by the stream. What is the problem with SimpleDataFormat.

From SimpleDateFormat documentation .

Date formats are not syncing. It is recommended that you create separate instances of the format for each stream. If multiple threads access the format at the same time, it must be synchronized externally.



If SimpleDateFormat was stateless, or written to make its state thread safe, then a yes static final would be enough to be thread safe.

However, if you want to share the same SimpleDataFormat instance between threads, you first need to synchronize the threads to the same monitor. Otherwise, it is recommended that you create a new SimpleDateFormat instance for each thread, or create a new instance as needed, or use ThreadLocal or a similar mechanism.

+3


source


The class is SimpleDateFormat

out of sync.

You can look at this question for more information. Hope it helps.

+2


source







All Articles