Immutability doesn’t guarantee thread safety

With the introduction of the new Java Memory Model (JMM) in Java 5 (JSR-133) a lot of unclearities have been removed from Java regarding immutable classes and thread safety. Under the new JMM it is now perfectly clear that the immutable nature of a class doesn’t guarantee that it is thread safe. Take a look at the following class:

public class MyInt{
    private int x;

    public MyInt(int y){
        this.x = y;
    }

    public int getValue(){
        return x;
    }
}

Reorderings and Visibility

MyInt is not thread safe by nature, even though it is immutable. I hope you wonder why. To understand what can go wrong, I have to introduce 2 concepts:

  1. reorderings: the compiler (Javac, JIT, CPU etc) is allowed to reorder instruction to improve performance. To name a few techniques that rely on reordering:
    1. locality: reads/writes to variables can be grouped to increase the chance of cache hit
    2. dynamic scheduling: to prevent that a CPU has to wait (and do nothing) for instructions in the pipeline (maybe memory access is delaying), it can execute unrelated instructions.

    There are more techniques, and you are never sure which techniques are used because Java is platform independent. You just need to remember that instructions can be reordered unless this is prevented.

  2. visibility: inside a single thread all reads/writes to a variable need to be visible, but no guarantees are made with normal variables that changes made in by some thread to a variable, are visible in another thread. Only when there is a happens-before edge between a write and a read, you are sure that the change is visible. The reason why this strange behavior exists is performance. Because of the strong memory coherence most CPU have, visibility problems normally won’t occur that often.

So what can go wrong with MyInt?

Constructors are not treated special by the compiler (JIT, CPU etc) so it is allowed to reorder instructions from the constructor and instructions that come after the constructor. In the case of the MyInt it is allowed that the assignment of a newly created instance of of MyInt is assigned to a variable before the constructor has run. This reordering is never visible in the executing thread (within-thread if-serial semantics), but if another thread is going to read x, it could see a partially created MyInt and sees 0 (the default value of an int member variable) at one moment, and the next moment it sees the correct value for x. This problem can be fixed by making x final because this prevents reordering. Under the old JMM, making the field final even is not a solution.

Another problem is that the write to x by the constructing-thread, and the read from x by another thread, doesn’t need to have a happens-before edge. If this edge is missing, no guarantees are made that a change made in one thread, is visible in another thread (in other words, x is not safely published). The consequence is that the other thread doesn’t need to see the constructed value (ever!) and still sees the initial value. This visibility problem can be solved by making x final (volatile would also be a working solution).

Conclusion

Not all immutable classes are thread safe by definition, only proper created ones are. The simplest thing that can be done is making variables final, if these can be set in the constructor. In case of setters, reordering and visibility problems can be prevented by making the field volatile or make sure that the field is always used in a synchronized context (eg synchronized getter/setter or a Lock).

The new JMM has a new and very useful property: save hand off. It allows objects with visibility and reordering issues to be used safely in a multi threaded environment because reorderings and visibility problems are prevented. Not properly created immutable classes can be passed through such a structure without worrying about these issues. But if you have the chance, try to do it good from day one.

If you want to learn more about the JMM, I suggest reading “Java Concurrency in Practice”.

22 Responses to Immutability doesn’t guarantee thread safety

  1. I second the recommendation for “Java Concurrency in Practice” (by Brian Goetz). It’s THE book on the concurrency API.

    For this example, to make it truly immutable, the class should be declared final in addition to the instance variable x. Otherwise it could be subclassed and made mutable.

  2. Mikael Grev says:

    If you want to read up on the mutability/immutability in practical terms I’ve written a little article about it a while ago: http://www.javalobby.org/articles/immutable/index.jsp

  3. Vijay says:

    I think that the following class is immutable and Thread-safe in Java 5.0 and higher:

    public class MyInt{
    private final int x;

    public MyInt(int y){
    this.x = y;
    }

    public int getValue(){
    return x;
    }
    }

  4. Nils says:

    Sounds to me like Java’s Threading model is terribly broken. A high-level language should hide such low-level details.

    • me says:

      It’s just the way machines work natively. The same problems exist in C++ and C, just that synchronization is much harder 🙂 If you want to completely hide this problem, then every load must be preceded by a cach invalidation and every store must be followed by a cach flush, disabling caches effectively. There is no performance without caches in today’s machines, as memory performance is vastly slower than CPU performance.

  5. […] out this interesting post Immutability doesn’t guarantee thread safety I guess we all have to worry about thread even corrupting our data (even more then […]

  6. Your example object is not immutable. Make the private attribute final as well. No need to make the class final, that is an unfortunate overloading of the final keyword. If you were storing any objects rather than basic types, you’d also have to worry about cloning. Immutability is wonderful, but it’s not as easy as it initially looks. 🙂

  7. TBD2 says:

    Is this new to anybody?! This has been a problem for years and anybody who hasn´t been aware of it shouldn´t be writing serious apps. There are numerous articles on this subject. See http://www.javaworld.com/jw-02-2001/jw-0209-double.html (from 2001)

  8. pveentjer says:

    It is not new to me, but it appears that not everybody knows it. That is why I decided to create a blogpost about it. I think that 99% of the developers are totally unaware of the JMM.

  9. ray says:

    The example is not appopriate. It breaks one of the definition of immutable class. The attribute of an immutable class has to be ‘final’. Immutable class is thread safe, period.

  10. pveentjer says:

    Hi Ray, thanks for your reply

    It depends on the definition of immutable and not everyone agrees with this definition. In most cases I prefer using final fields, but in some cases it is not very practical because of too complex constructors. In these cases I use default values and setters for these fields.

    After the object has been constructed (and maybe a few setters are called) the object can be considered immutable because the state isn’t going to change (for example an EmployeeManager

    And from a single threaded point of view, the example I have given is immutable. Within that thread it is impossible to change the value or to see an inconsistent value (within-thread if-serial-semantics).

  11. Chris says:

    Very nice blog and site.
    Thanks Peter for reminding me of this subtle issue. Especially, reorderings and the final keyword for private int x. It was new to me.

  12. Ferdhz says:

    Thanks for enlightening me! I’m totally unaware of the JMM and its effects on my real-time applications. I think i have to get a copy of “Java Concurrency in Practice” book.

  13. Attilio says:

    Very interesting issue. Thank you for your detailed explanation.
    I think I will never learn enough about concurrency.

  14. Khl says:

    a good article,
    have just aremark:”Reorderings and Visibility” would be clear to name it “Reordering and Isolation”

  15. Anonymous Coward says:

    Many people already commented out the obvious: in Java immutables classes are using final fields and everybody agrees on this in the Java world.

    What I want to add is that of course instead of providing explicitely a public constructor if you used a factory then even your broken example would be immutable.

    Constructors break encapsulation, remember that.

  16. Zing says:

    “Immutable class is thread safe, period.”

    Not before 1.5 it wasn’t. 🙂

  17. Eric says:

    It seems OK, but I am just wondering: Before the construction complete, how can you get the reference to the object? If constructors are so dangerous, why doesn’t Java provide synchronized to constructors?

    • pveentjer says:

      Hi Eric,

      it has to do with the bytecode from the constructor code. Constructing a new object takes more than one step:
      1) create the uninitialised but new object
      2) run the constructor
      3) assign the reference of the new object to some non local variable

      Bytecode can be reordered, so it could be that parts of step2 are reordered with step 3. When this happens a different thread could have a reference to that object that has not fully been constructed.

      Perhaps you can have a look at the following blogpost:

      JMM: Constructors don’t have visiblity/reordering problems

  18. Eric says:

    Thanks for your response.
    If I have many fields to be initialized in a mutable class, sychronizing the constructor would be a better solution than synchronizing the accesses to each field, right? But in the Java Language Specification, it said,” There is no practical need for a constructor to be synchronized, because it would lock the object under construction, which is normally not made available to other threads until all constructors for the object have completed their work.” in Section 8.8.3. http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.8.3
    Therefore, I think, it is the JVM’s responsibility, to guarentee the object is completedly constructed before the reference is returned. Yes the constructor is a normal method, but the “new” operator should guarentee that.

    • Warren Dew says:

      Eric, your original question was spot on; Java really needs to permit constructors to be synchronized. Apparently when the Java language spec was originally written, the writers assumed that constructors would automatically be synchronized, but it wasn’t made explicit and the VM implementers didn’t synchronized them for efficiency reasons.

      For classes without inheritance, you can get the same effect by putting a synchronized block inside the constructor. Unfortunately this does not work for classes with inheritance. Sadly, the only option for complex classes with the current state of Java is to have an empty private constructor and do initialization in static factory functions.

  19. Eric says:

    I have read the article “JMM: Constructors don’t have visiblity/reordering problems”. Accordint to that,”from a technical point of view there are no issues” in the MyInt class. What we should do is to guarentee a safe publication. I recoment this article: http://www.ibm.com/developerworks/java/library/j-jtp0618.html

Leave a reply to Mikael Grev Cancel reply