41

Lets say for example, a thread is creating and populating the reference variable of an immutable class by creating its object and another thread kicks in before the first one completes and creates another object of the immutable class, won't the immutable class usage be thread unsafe?

Creating an immutable object also means that all fields has to be marked as final.

it may be necessary to ensure correct behavior if a reference to a newly created instance is passed from one thread to another without synchronization

Are they trying to say that the other thread may re-point the reference variable to some other object of the immutable class and that way the threads will be pointing to different objects leaving the state inconsistent?

giannis christofakis
  • 8,201
  • 4
  • 54
  • 65
Taran Singh
  • 583
  • 2
  • 6
  • 13
  • 2
    No. Each thread is creating a distinct instance of an immutable object. I see no thread risk at all. – Hovercraft Full Of Eels Feb 16 '12 at 00:00
  • [Does Immutability Really Mean Thread Safety?](https://dzone.com/articles/do-immutability-really-means) – LShi Sep 15 '17 at 01:40
  • +No, the immutable model can **contain a non-thread-safe method** (do a logic which expected to run synchronized + this method not change the internal state of the immutable model) – Ahmed Nabil Mar 28 '21 at 03:24

6 Answers6

38

Actually immutable objects are always thread-safe, but its references may not be.

Confused?? you shouldn't be:-

Going back to basic: Thread-safe simply means that two or more threads must work in coordination on the shared resource or object. They shouldn't over-ride the changes done by any other thread.

Now String is an immutable class, whenever a thread tries to change it, it simply end up creating a new object. So simply even the same thread can't make any changes to the original object & talking about the other thread would be like going to Sun but the catch here is that generally we use the same old reference to point that newly created object.

When we do code, we evaluate any change in object with the reference only.

Statement 1: String str = "123"; // initially string shared to two threads

Statement 2: str = str+"FirstThread"; // to be executed by thread one

Statement 3: str=str+"SecondThread"; // to be executed by thread two

Now since there is no synchronize, volatile or final keywords to tell compiler to skip using its intelligence for optimization (any reordering or caching things), this code can be run in following manner.

  1. Load Statement2, so str = "123"+"FirstThread"
  2. Load Statement3, so str = "123"+"SecondThread"
  3. Store Statement3, so str = "123SecondThread"
  4. Store Statement2, so str = "123FirstThread"

and finally the value in reference str="123FirstThread" and for sometime if we assume that luckily our GC thread is sleeping, that our immutable objects still exist untouched in our string pool.

So, Immutable objects are always thread-safe, but their references may not be. To make their references thread-safe, we may need to access them from synchronized blocks/methods.

amandeep1991
  • 1,344
  • 13
  • 17
  • Consider a collection, ArrayList of string, ArrayList l = list1; l = list2; where list1 and list2 are already created before, so with first statement l points to list1 and with second it points to list2, so I guess ArrayList is also thread safe but it's reference is not thread safe ?......Let me know what am I missing here – Akki Jun 14 '19 at 10:40
  • 1
    @Akki No, ArrayList cannot be considered thread-safe unless we take care of the concurrency manually using things like synchronization. You are considering two references here, that's why it seems like it is thread-safe, which can be true for any other class. What we are discussing over here is immutability with thread safety and ArrayList is not immutable (unless you have used Collections.unmodifiableList). – ankur_rajput Feb 25 '21 at 17:09
16

In addition to other answers posted already, immutable objects once created, they cannot be modified further. Hence they are essentially read-only.

And as we all know, read-only things are always thread-safe. Even in databases, multiple queries can read same rows simultaneously, but if you want to modify something, you need exclusive lock for that.

Bhushan
  • 18,329
  • 31
  • 104
  • 137
12

Immutable objects are thread safe, but why?

An immutable object is an object that is no longer modified once it has been constructed. If in addition, the immutable object is only made accessible to other thread after it has been constructed, and this is done using proper synchronization, all threads will see the same valid state of the object.

If one thread is creating populating the reference variable of the immutable class by creating its object and at the second time the other thread kicks in before the first thread completes and creates another object of the immutable class, won't the immutable class usage be thread unsafe?

No. What makes you think so? An object's thread safety is completely unaffected by what you do to other objects of the same class.

Are they trying to say that the other thread may re-point the reference variable to some other object of the immutable class and that way the threads will be pointing to different objects leaving the state inconsistent?

They are trying to say that whenever you pass something from one thread to another, even if it is just a reference to an immutable object, you need to synchronize the threads. (For instance, if you pass the reference from one thread to another by storing it in an object or a static field, that object or field is accessed by several threads, and must be thread-safe)

meriton
  • 68,356
  • 14
  • 108
  • 175
  • 2
    Note that the part about "only made accessible after construction" can be made trivial by using final fields only (and since the object is immutable no reason not do). The java memory model gives all the [guarantees](http://java.sun.com/docs/books/jls/third_edition/html/memory.html#66562) we need if we avoid some obvious mistakes. – Voo Feb 16 '12 at 00:51
  • @Voo: I don't think it's quite that fool-proof. Final fields are required to be assigned when the constructor completes, but it's quite possible for the constructor to store `this` into an object accessible by another thread before assigning all final fields. – meriton Feb 16 '12 at 02:06
  • 1
    Yes doing something like `someCollection.add(this)` and co are exactly the obvious mistakes we have to avoid (but then I think it's common knowledge that leaking this from the constructor is almost always broken for other reasons as well). Even if the leaking instruction is the *last* one in the constructor, the guarantees do **not** apply (see 3rd paragraph for this). – Voo Feb 16 '12 at 02:17
  • Interesting, thanks for pointing out the special significance of constructor completion. – meriton Feb 16 '12 at 02:29
6

Thread safety is data sharing safety, And because in your code you make decisions based on the data your objects hold, the integrity and deterministic behaviour of it is vital. i.e

Imagine we have a shared boolean instance variable across two threads that are about to execute a method with the following logic

  • If flag is false, then I print "false" and then I set the flag back to true.
  • If flag is true, then I print "true" and then I set the flag back to false.

If you run continuously in a single thread loop, you will have a deterministic output which will look like:

false - true - false - true - false - true - false ...

But, if you ran the same code with two threads, then, the output of your output is not deterministic anymore, the reason is that the thread A can wake up, read the flag, see that is false, but before it can do anything, thread B wakes up and reads the flag, which is also false!! So both will print false... And this is only one problematic scenario I can think of... As you can see, this is bad.

If you take out the updates of the equation the problem is gone, just because you are eliminating all the risks associated with data sync. that's why we say that immutable objects are thread safe.

It is important to note though, that immutable objects are not always the solution, you may have a case of data that you need to share among different threads, in this cases there are many techniques that go beyond the plain synchronization and that can make a whole lot of difference in the performance of your application, but this is a complete different subject.

Immutable objects are important to guarantee that the areas of the application that we are sure that don't need to be updated, are not updated, so we know for sure that we are not going to have multithreading issues

You probably might be interested in taking a look at a couple of books:

This is the most popular: http://www.amazon.co.uk/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ref=sr_1_1?ie=UTF8&qid=1329352696&sr=8-1

But I personally prefer this one: http://www.amazon.co.uk/Concurrency-State-Models-Java-Programs/dp/0470093552/ref=sr_1_3?ie=UTF8&qid=1329352696&sr=8-3

Be aware that multithreading is probably the trickiest aspect of any application!

Jim Buck
  • 2,383
  • 23
  • 42
Alberto Gutierrez
  • 1,588
  • 7
  • 9
2

Immutability doesn't imply thread safety.In the sense, the reference to an immutable object can be altered, even after it is created.

//No setters provided
class ImmutableValue
{

     private final int value = 0;

     public ImmutableValue(int value)
     {
          this.value = value;
     }

     public int getValue()
     {
          return value;
     }
}

public class ImmutableValueUser{
  private ImmutableValue currentValue = null;//currentValue reference can be changed even after the referred underlying ImmutableValue object has been constructed.

  public ImmutableValue getValue(){
    return currentValue;
  }

  public void setValue(ImmutableValue newValue){
    this.currentValue = newValue;
  }

}
Binita Bharati
  • 5,239
  • 1
  • 43
  • 24
0

Two threads will not be creating the same object, so no problem there.

With regards to 'it may be necessary to ensure...', what they are saying is that if you DON'T make all fields final, you will have to ensure correct behavior yourself.

MikeL
  • 48
  • 6