Shirgill Farhan Ansari Shirgill Farhan Ansari - 1 year ago 44
Java Question

Immutable Objects and Initialization Safety with Thread Safety

A note from the The Java Concurrency In Practice

Immutable objects can be used safely by any thread without additional
synchronization, even when synchronization is not used to publish them

What I get is that they are thread - safe.

A snippet from Jeremy Manson blog-

class String {
// Don't do this, either.
static String lastConstructed;
private final byte[] bytes;
public String(byte[] value) {
bytes = new byte[value.length];
System.arraycopy(value, 0, bytes, 0, value.length);
lastConstructed = this;

Since the this reference is being stored in lastConstructed" hence Escaping the constructor

Ofcourse, it would work if you made lastConstructed volatile (postJDK5+ semantics)

One of the questions asked there is-

If lastConstructed was volatile but then the reference was unsafely
published to another thread, then the String would not be immutable.

to which Jeremy's reply was-

It wouldn't be thread-safe because it was immutable, but it would be thread-safe because lastConstructed was volatile.

I perfectly understand that it would be thread-safe because lastConstructed was volatile, but I don't get It wouldn't be thread-safe because it was immutable.

Why? The note from Concurrency In Practice says Immutable objects can be used safely by any thread (i.e Thread Safety guarantee). If something is immutable, then it is thread safe.

Please suggest.

Answer Source

A common mis-understanding is that you have Object fields in Java. You only have references and primitives. This means that

static String lastConstructed;

The field lastConstructed is a mutable reference. It's visibility is not thread safe. Having an immutable object doesn't confer any properties on a reference to that object.

Similarly if you have a final field, this doesn't make your Object immutable.

final Date today = new Date();

today is not immutable just because you made one reference to it final.

A more subtle on is in the use of volatile You have to be careful as to whether you are reading or write the volatile value. Even if you do

volatile Date now = new Date();

now.setTime(System.currentTimeMillis()); // no thread safe.

There is two reasons this is not thread safe. 1) The access to now is a read not a write and secondly it occurs before the write in any case. What is required is a write barrier after. Something you see what appears to be nonsense.

now = now; // this adds a write barrier.

A related myth is that if you use a thread safe collection, any series of operations you perform is also thread safe. It's a bit like fairy dust, you just sprinkle it around and many of your bugs disappear, but this doesn't mean you really are thread safe.

In short, thread safety is like a chain of dependencies, if any aspect of how data is accessed is not thread safe, none of it is.

Note: adding some thread safe constructs can hide thread safety issues, but it doesn't fix them, it just means that some change in JVM, or OS or hardware will break your code in the future.