I replied to a question earlier about thread safety which did not get a definite answer (I think).
So I have been trying to convince myself that the design is broken (visibility) by having thousands of threads read and write that object – but I have not been able to get anything unexpected. That is obviously not a proof that it is thread safe, probably merely a proof of my own limitations!
I understand the risk of reordering but I don’t see how it could apply in that case, in the sense that the clone instance in the bar() method is local and the change on its fields is done before being released to the outside world with return, after which the instance is effectively immutable. So a thread looking at the returned object would see it with its bar field already set to the correct value…
So my question is: what kind of code Could you show a piece of code that uses IsItSafe and that could lead 2 threads to see different values of the bar field of a given instance of IsItSafe?
For reference and ease of reading I copy the code here:
public class IsItSafe implements Cloneable {
private int foo;
private int bar;
public IsItSafe foo(int foo) {
IsItSafe clone = clone();
clone.foo = foo;
return clone;
}
public IsItSafe bar(int bar) {
IsItSafe clone = clone();
clone.bar = bar;
return clone;
}
public int getFoo() {
return foo;
}
public int getBar() {
return bar;
}
protected IsItSafe clone() {
try {
return (IsItSafe) super.clone();
} catch (CloneNotSupportedException e) {
throw new Error(e);
}
}
}
Visibility problems can occur when a value your program has written to a variable is cached in the cpu cache and not written to RAM immediately. For this reason if thread A running on cpu A is writting a value without correct synchronization and thread B reads this value from cpu B he might see a stale value in RAM and not the most recent value (present only in the cpu cache of processor A).
In the example given you are using none of the mechanisms Java provides to ensure safe publication. That is synchronization, volatile or final fields set in the constructor.
Therefore one could imagine that in your example the reference to the create
cloneobject becomes availabe but the values written to clones fields remains in the cpu cache. In this case other threads would not be able to read the up to date values.To give some reference. Look at this example
class FinalFieldExample { final int x; int y; static FinalFieldExample f; public FinalFieldExample() { x = 3; y = 4; } static void writer() { f = new FinalFieldExample(); } static void reader() { if (f != null) { int i = f.x; int j = f.y; } } }The argument you are making would hold for this example as well, wouldn’t it? The instance is created, fields set in the constructor etc. However it is not thread-safe, since the value written to
yneeds not become visible to other threads.(The cited example is from JSR 133 (Java Memory Model) FAQ: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#reordering)
Update: You have asked for code that demonstrates the problem. I asked a similar (more open) question once: How to demonstrate java multithreading visibility problems?
The interesting thing with the code sample given is, that it will behave differently with different minor versions of Java, on different operating systems and wether using the client or server jvm. In that regard I found the sample quite interesting.
What is important to note is, that it might well be impossible to actually create sample code that leads to a visibility problem with your code today. However next year cpu generation might implement a different caching policy and suddenly the problem appears. If you follow the guidelines of the Java Language Specification your save.