Yes, the private member variable bar should be final right? But actually, in this instance, it is an atomic operation to simply read the value of an int. So is this technically thread safe?
class Foo {
private int bar;
public Foo(int bar) {
this.bar = bar;
}
public int getBar() {
return bar;
}
}
// assume infinite number of threads repeatedly calling getBar on the same instance of Foo.
EDIT:
Assume that this is all of the code for the Foo class; any threads with a reference to a Foo instance will not be able to change the value of bar (without going to such lengths as using reflection etc.)
Final update: so my first conclusion happened to be right, just my reasoning was faulty 🙁 I re-edited my answer to make it somewhat coherent, not to hide the traces of my earlier blunder.
Conclusion
As @Wyzard pointed out, even though there is no way to change
barafter construction,Foois still not thread safe. The problem is not atomicity but visibility. If thread 1 is changing the value ofbarin the constructor (from its default value of 0), there is no guarantee when other threads will get to see the new value (or whether they see it at all).So
foolooks like an immutable object. Quoting from Java Concurrency in Practice, section 3.4:Foolooks OK on 1) and 3), but not 2). And that is a crucial point, due to the reasoning above. Declaring a variablefinalis one way of ensuring its visibility between different threads. The other means are declaringbarvolatile, or synchronizing its access method(s). But of course, in case of an immutable object, neither of these would make much sense.Final Fields
So why do
finalfields guarantee visibility? Answer from Java Concurrency in Practice, section 3.5.2:And what happens if the field is not final? Other threads may silently see a stale value of the field. There is no exception or any kind of warning – that is one reason why these kinds of bugs are so difficult to trace.