Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to publish StringBuffer safely?

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...

like image 235
St.Antario Avatar asked Apr 06 '16 09:04

St.Antario


2 Answers

Can you help to understand this? Maybe I missed something...

AFAIR after JSR-133 it is guaranteed that final 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 init

upd: via Brian Goetz

Under the new memory model, there is something similar to a happens-before relationship between the write of a final field in a constructor and the initial load of a shared reference to that object in another thread. When the constructor completes, all of the writes to final fields (and to variables reachable indirectly through those final fields) become "frozen," and any thread that obtains a reference to that object after the freeze is guaranteed to see the frozen values for all frozen fields. Writes that initialize final fields will not be reordered with operations following the freeze associated with the constructor.

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

like image 195
Cootri Avatar answered Sep 19 '22 06:09

Cootri


See the javadoc for StringBuffer.

String buffers are safe for use by multiple threads. The methods are synchronized where necessary so that all the operations on any particular instance behave as if they occur in some serial order that is consistent with the order of the method calls made by each of the individual threads involved.

That should be sufficient guarantee.

like image 30
OldCurmudgeon Avatar answered Sep 19 '22 06:09

OldCurmudgeon