Java concurrency in practice book has given an example for unsafe publication
public class Holder
{
private int n;
public Holder(int n)
{
this.n = n;
}
public void assertSanity()
{
if (n != n)
throw new AssertionError("This statement is false.");
}
}
The above code seems to be thread safe. It would not be thread safe if n is public variable. Is the book example wrong?
Safe publication is about memory visibility. The concept of memory visibility is a bit trickier than other thread safety issues such as race conditions.
Memory visibility issues arise when actions performed by one thread in certain order appear to be performed in different order for another thread (it may be caused by optimizations made by compiler or CPU).
In your case:
// Thread A
h = new Holder(42);
// Thread B
h.assertSanity();
For Thread A, n
is certainly initialized before h
.
But in absense of safe publication it's not guaranteed to be the same for Thread B. Thread B may see h
in initialized state, but n
won't be initialzed yet. Moreover, the state of n
as observed by Thread B may change during evaluation of n != n
, causing assertSanity()
to throw an exception.
Note that this problem is not something that is guaranteed to happen in all cases. You will probably never see this happening, but Java Memory Model doesn't guarantee correctness in this case nonetheless.
It's not thread safe, because when the object of the class is created Holder.n
is assigned a default value of 0
.
Because of that, some threads can see the value 0
and others the value n
that is passed to constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With