Performance Zone is brought to you in partnership with:

Peter is a DZone MVB and is not an employee of DZone and has posted 161 posts at DZone. You can read more from them at their website. View Full User Profile

Why a synchronized StringBuffer was never a good idea

04.25.2013
| 10879 views |
  • submit to reddit

Introduction

StringBuffer is a synchronized class for mutable strings.  The main problem with making it synchronized is that

  1. It was usually used as a local variable so making it synchronized just made it slower.
  2. It was never a good idea to use it in a multi-threaded way.  This problem is that developers assumed that methods which used StringBuffer were themselves thread safe when they were not.

The problem with StringBuffer

This is an example from a real class which is used in production in many trading systems. It's not a commonly used but you might assume that StringBuffer gives you thread safety, when it doesn't.
    private StringBuffer sb = new StringBuffer();

    public void addProperty(String name, String value) {
        if (value != null && value.length() > 0) {
            if (sb.length() > 0) {
                sb.append(',');
            }
            sb.append(name).append('=').append(value);
        }
    }
While individual calls are thread safe, multiple calls are not.  It is almost impossible to find a good use for StringBuffer that doesn't involve multiple calls (including toString)

A puzzle

Imagine three threads call (in no particular order)
 T1: addProperty("a", "b");
T2: addProperty("c", "d");
T3: sb.toString();
write a program which will generate every possible output of T3's sb.toString()   I found 89.  With thread safety, you might reduce this to 4. Note: if you used StringBuilder it would be worse, but at least you might not assume your method is thread safe when it is not. e.g. SimpleDateFormat uses StringBuffer ;)




Published at DZone with permission of Peter Lawrey, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Vishal Jain replied on Thu, 2013/04/25 - 5:37am

You are right, I've also seen such code in production many times. I think every java developer should read Java concurrency in practice book compulsarily. I guess this wouldn't have happened if they knew the basics of concurrency. Thanks for the post. 

Hector Adolfo Alonso replied on Thu, 2013/04/25 - 9:26pm

Hi Peter:

   Good point !

a. - sb.append ("Hi") is synchronized with respect to sb. While some thread is executing this method, no other thread can execute another synchronized method on sb.

b. - If a thread runs sb.append("Good").append("morning").append("Peter"), while another runs sb.append("Good").append("night").append ("Peter"), six append ("...") invocations on sb will be synchronized on sb, but nothing guarantees that the first three were executed before or after the last three. You may obtain multiple combinations for sb content.

c. - synchronized (sb) {sb.append("Good").append("morning").append("Peter!");} is synchronized with respect to sb. While some thread executes this synchronized block, no other thread can execute another method or synchronized block on sb.

d. - If a thread runs
synchronized (sb) {
   sb.append("Good").append("morning").append("Peter");
}

while another runs
synchronized (sb) {
   sb.append("Good").append("night").append("Peter");
}

both blocks are synchronized with respect to sb. You may ensure that you get only 2 possible contents for sb:

- "Good morning Peter! Good nigth Peter!"
or
- "Good night Peter! Good morning Peter!"

   Javadoc for SimpleDateFormat states that date formats are not thread safe.

Héctor./

Peter Lawrey replied on Fri, 2013/04/26 - 2:54am in response to: Hector Adolfo Alonso

If you are forced to synchronized your accesses to an object externally, it is simpler and clearer IMHO to use an unsynchronized class. I have seen many examples of code which doesn't worry about synchronization because it is using a synchronized StringBuffer.  

With biased locking, this can make race conditions even harder to detect.


Dan Howard replied on Fri, 2013/04/26 - 5:47am

Ever heard of StringBuilder? What is this 1997?

Peter Lawrey replied on Fri, 2013/04/26 - 10:06am in response to: Dan Howard

Java 5.0 came out in 2004.

Libraries still use StringBuffer, just in case there is some multi-threaded is using it even though it is quite likely it is not thread safe anyway.

BTW Java 7 update 21 src.zip

Occurances of "new StringBuffer": 571
Occurances of "new StringBuilder": 265

We a still a long way from the JDK mostly using StringBuilder. :]



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.