I've read some articles about String
s and StringBuilder
s benefits and downsides in Java Programmming language, In one of the articles, the author wrote : StringBuilders are not Thread safe so in multiple threads use StringBuffer
.
Now I can't understand the meaning of that.
Could you please show me the difference of Stirng
, StirngBuilder
and StringBuffer
especially in the context of "Thread safety". (describing with code can be very good but if it is not possible, any hint will be appreciated).
If multiple thread tries to change the StringBuilder object value then the result will be strange. See the below example,
If many thread calls addProperty method then the result will be strange (unpredictable result).
Finally when you call sb.toString() the result will be unpredictable. For example, it may bring output like
1=2,ac=d=b,e=f
, but your expectation would be1=2,a=b,c=d,e=f
If multiple threads are modifying the same instance of a
StringBuilder
, the result can be unexpected - i.e. some of the modifications may be lost. That's why you should use StringBuffer in such situations. If, however, each threadStringBuilder
instance can be modified by only one thread, it is better to useStringBuilder
, since it would be more efficient (thread safety comes with a performance cost).Because StringBuilder is not a synchronized one whereas StringBuffer is a synchronized one.When using StringBuilder in a multithreaded environment multiple threads can acess the StringBuilder object simultaneously and the output it produces can't be predicted hence StringBuilder is not a thread safe...
Using StringBuffer we can overcome the problem of Threads safety where the StringBuffer is a thread safety because it is synchronized where only one thread can access at a time so the output it produces can be expected and predicted.
The thread-safety issue with
StringBuilder
is that method calls on aStringBuilder
do not synchronize.Consider the implementation of the
StringBuilder.append(char)
method:Now suppose that you have two thread that are sharing a
StringBuilder
instance, and both attempt to append a character at the same time. Suppose that they both get to thevalue[count++] = c;
statement at the same time, and thatcount
is1
. Each one will write its character into the buffer atvalue[1]
, and then updatecount
. Obviously only one character can be stored there ... so the other one will be lost. In addition, one of the increments tocount
will probably be lost.Worse than that, the
value[count++] = c;
statement can fail even if the two threads don't arrive there at the same time. The reason is that the Java memory model says that unless there is proper synchronization (a "happens before" relationship), it is not guaranteed that the second thread will see the memory updates made by the first thread. What actually happens depends on whether and when the first thread's updates are written through to main memory.Now lets look at
StringBuffer.append(char)
:Here we see that the
append
method issynchronized
. This means two things:Two threads cannot execute the superclass
append
method on the sameStringBuffer
object at the same time. Thus the first scenario cannot happen.The
synchronize
means that there is ahappens before
between successive calls toStringBuffer.append
made by different threads. That means that the later thread is guaranteed to see the updates made in the earlier one.The
String
case is different again. If we examine the code, we will see that there is no overt synchronization. But that's OK, because aString
object is effectively immutable; i.e are no methods in theString
API that will result in an externally observable change in theString
object's state. In addition:The special behaviour of
final
instance variables and constructors means that the all threads will see the correct initial state for anyString
.In the one place where the
String
is mutable behind the scenes, thehashCode()
method will work correctly whether or not a thread sees the most recent changes to thehash
variable.References: