How to publish a StringBuffer safely?

Since StringBuffer is thread safe, it can be safely published. Consider the public constructor of StringBuffer ( sources ):

 public StringBuffer() { super(16); } 

where super(16) stands for this:

 AbstractStringBuilder(int capacity) { value = new char[capacity]; } 

where is the value declared as

 char[] value; 

QUESTION: How to publish a StringBuffer safely?

I have the following class:

 public class Holder{ public final StringBuffer sb = new StringBuffer(); } 

Can a publication be considered safe? I think he can’t.

final ensures that we see the new sb link value. But writing to the internal sb state inside AbstractStringBuilder(int capacity) not synchronized. Therefore, there is no order happens-before , which, in turn, means that reading from value occurred when sb.append(2); called sb.append(2); and writing to value in the racy constructor.

Can you help figure this out? Maybe I missed something ...

+5
source share
3 answers

Can you help figure this out? Maybe I missed something ...

AFAIR after JSR-133 ensures that the final field for the class initialized as in your example does not contain race conditions during the instantiation process, and only after init

update: via Brian Goetz

The new memory model has something similar to the relationship between writing the final field in the constructor and loading the general link to this object in another thread. When the constructor completes, all records in the final fields (and variables accessed indirectly through these final fields) become "frozen", and any thread that receives a reference to this object after freezing is guaranteed to see frozen values ​​for all frozen fields. Writes that the initialization of the final fields will not be reordered using the operations following the freeze associated with the constructor.

IMHO your question (and understanding of concurrency) is very good, because this is not an obvious language / platform development function, and it was fixed only in Java SE 5.0

+4
source

See javadoc for StringBuffer .

String buffers are safe for use by multiple threads. If necessary, the methods are synchronized, so all operations on a particular instance behave as if they were encountered in a certain sequential order , which is consistent with the order of method calls performed by each of the individual threads.

This should be a sufficient guarantee.

+2
source

Creating an sb instance variable is thread safe because it runs at the same time as creating the Holder instance.

The reason this is thread-safe is an instance variable, and there is no way that thread 1 can start creating an instance of Holder (and by associating it with a new StringBuffer ), and then for the second thread to go into and start the constructor to execute same instance.

That is, if your code has two threads that fall into lines

 Holder h = new Holder(); 

You will have two separate instances of Holder, and then a race for which h is assigned, which is another problem.

+2
source

Source: https://habr.com/ru/post/1246544/


All Articles