Since StringBuffer
is thread safe it can safely be published. Consider the public constructor of StringBuffer
( sources ):
public StringBuffer() {
super(16);
}
where super(16)
designates this one:
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
where value declared as
char[] value;
QUESTION: How to publish StringBuffer
safely?
I've got the following class:
public class Holder{
public final StringBuffer sb = new StringBuffer();
}
Can it be considered as safe-publication? I think, it cannot.
final
guarantees that we'll see a fresh value of the reference sb
. But writing to the sb
's internal state within AbstractStringBuilder(int capacity)
is not synchronized. Therefore there's no happens-before
order which in turn means that read from value
occured when invoking sb.append(2);
and writing to value
in the constructor are racy.
Can you help to understand this? Maybe I missed something...
See the javadoc for StringBuffer.
That should be sufficient guarantee.
Creating the instance variable of
sb
is thread-safe since it is done at the same time as creating an instance ofHolder
.The reason it is thread-safe is it's an instance variable and there is no way thread 1 can start constructing an instance of
Holder
(and by association a newStringBuffer
) and then for a second thread to jump in and start running through the constructor for the same instance.That is if your code has two threads that both came across the lines
You'd end up with two separate instances of Holder and then a race for which is assigned to
h
, which is a different problem.AFAIR after
JSR-133
it is guaranteed thatfinal
field of the class that is initialized like in your example is free from race condition during instantiation process and only the correct value will be exposed after initupd: via Brian Goetz
IMHO your question (and concurrency understanding) is very good because it is not an obvious language / platform design feature and it was fixed only in Java SE 5.0