2

I was reading this Stackoverflow thread about using StringBuilder versus StringBuffer.

The bottom line seemed to be that the two collections were the same thing except that a StringBuffer is synchronized, is a thread safe and does a little less well in performance as compared to StringBuilder which are not those things.

Someone brought up how a similar relationship existed between ArrayList and Vector.

Is it a good (safe) rule of thumb to NOT use synchronized collections ( or anything else ) unless I am consciously creating multiple threads?

In other words, I got the message "Use the new StringBuilder wherever possible.", what I want to know is, how can I be sure it is possible?

Am I safe using non-synchronized collections as long as I don't create new threads intentionally?

Community
  • 1
  • 1
Steve
  • 3,127
  • 14
  • 56
  • 96

7 Answers7

5

Use unsynchronized things until you're sure that you need synchronization.

Part of the issue with e.g. StringBuffer and Vector is that they're not always synchronized in the right way. For Vector, it's not always what you need to have every operation be synchronized individually; frequently what you actually want is to synchronize blocks of operations...for which Vector isn't necessarily any better than ArrayList or a Collections.synchronizedList.

When you know you're using concurrency and multiple threads, then work out the details of what synchronization you need, but just swapping StringBuffer in for StringBuilder will only give you a false sense of security -- even if you decide to use concurrency later, that's not necessarily the right kind of concurrency.

(If you're not currently using threading, then it's absolutely fine -- even recommended -- to find-and-replace StringBuffer to StringBuilder. The above arguments are for the reverse direction.)

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
1

I would say always use non-blocking anything until you know how to answer this question yourself. It's really easy to synchronize everything its also really easy to create and start threads. It takes a while to understand when to use a synchronized and when to create a thread.

You should start by reading Java Concurrency in Practice.

John Vint
  • 39,695
  • 7
  • 78
  • 108
  • Is it possible for me to start a new thread without knowing that I am doing so( ie writing new Thread() )? If I don't do that, am I safe with nonsynchronized collections? – Steve Aug 09 '12 at 16:20
  • 1
    Unless you create a `new Thread` or use say an `ExecutorService` and you write all the code yourself you do not need a synchronized anything. The only exception to this is if you are creating a Swing App. With that exception it would be rare. – John Vint Aug 09 '12 at 16:23
  • It really depends. If you are using a third party library that you pass some listeners and/or callbacks to it could very well invoke them on different threads. – Matt Wonlaw Aug 09 '12 at 16:24
  • But again it brings to my original argument. If you aren't sure when to use it, its probably safe to assume you won't use it most effeciently (I say this from experience because I have had the same problem in the past). Your best bet is to read up on concurrency through various books like JCiP and even Concurrent Programming in Java (to get a base foundation). – John Vint Aug 09 '12 at 16:24
1

It seem like you're asking multiple questions here. So, first of all, it is indeed a good idea to avoid synchronization unless absolutely necessary.

On your second question it is also safe to replace StringBuilder with StringBuffer and vice versa, unless their values can be changed from multiple threads.

Eugene Kuleshov
  • 31,461
  • 5
  • 66
  • 67
0

We are using StringBuilder instead of StringBuffer as we don't think so that multiple threads will cause us issues.

Bharat Sinha
  • 13,973
  • 6
  • 39
  • 63
0

Doing it on a whole code base automatically sounds a bit dangerous without further analysis, unless you are 100% positive that those objects (Vectors, StringBuffers) are not shared accross threads, or if the choice of a synchronized object was not driven by a thread safety analysis in the first place.

One simple case where you can do the swap without risk is local variables, which obviously can't be shared accross threads (unless you return them).

assylias
  • 321,522
  • 82
  • 660
  • 783
  • Good point. I think all of my StringBuffers exist within functions, so they are all local variables. – Steve Aug 09 '12 at 16:17
0

This link says it best:

* http://javahowto.blogspot.com/2006/08/stringbuilder-vs-stringbuffer.html

StringBuilder was introduced in JDK 1.5. What's the difference between StringBuilder and StringBuffer? According to javadoc, StringBuilder is designed as a replacement for StringBuffer in single-threaded usage. Their key differences in simple term:

  • StringBuffer is designed to be thread-safe and all public methods in StringBuffer are synchronized. StringBuilder does not handle thread-safety issue and none of its methods is synchronized.

  • StringBuilder has better performance than StringBuffer under most circumstances.

  • Use the new StringBuilder wherever possible.

From my own experience:

  • For any serious string manipulation, always use StringBuilder (never "String")

  • I've never had any occasion to use StringBuffer (I always just use "StringBuilder" instead).

  • Only if the same string-in-progress is being accessed concurrently from multiple threads should you even consider "StringBuffer". And even then, you might well find it easier/more efficient to use your own locking instead.

IMHO...

paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • I think the question asks for clarification on *"Use the new StringBuilder wherever possible."*, i.e. how do you make sure it is possible. – assylias Aug 09 '12 at 16:18
  • Exactly, I'm putting your phrase into my questions. Clear and to the point, thanks. – Steve Aug 09 '12 at 16:22
  • Two rules of thumb implied above: 1) if no threads: don't worry. Use StringBuilder ;) 2) if you have threads ... but the string-in-progress is a local variable: don't worry ;). Additionally: if you think you can do the locking better yourself - go for it. Use StringBuilder. Clear enough ;)? – paulsm4 Aug 09 '12 at 16:26
0

Is it a good (safe) rule of thumb to NOT use synchronized collections ( or anything else ) unless I am consciously creating multiple threads?

No it is not.

There are situations where multiple threads are involved, even though you don't consciously create them. For example, any application that uses Swing or Servlets has the potential for interactions between application code on different threads. (And you could even argue that you don't explicitly create threads if you use a standard thread-pool implementation.)

And further more, using a synchronized collection does not necessarily buy you thread safety.

But you are correct in the sense that using a synchronized data structure when there is no possibility of multiple threads using the data structure is (somewhat) wasteful. But nowhere like as wasteful as in the old days when mutexes were expensive.


In other words, I got the message "Use the new StringBuilder wherever possible.", what I want to know is, how can I be sure it is possible?

By understanding your code. Can the StringBuilder be seen by other threads? If not, then it safe to use it. Otherwise, the threads that share the StringBuilder need to synchronize. One way to do that might be to use a StringBuffer, but that won't necessarily give you the right synchronization granularity.

Here's a simple example:

  public String nTimes(String str, int n) {
      StringBuilder sb = new StringBuilder();
      for (int i = 1; i <= n; i++) sb.append(str);
      return sb.toString();
  }

In the above, the StringBuilder in sb can never be seen by another thread, so there is no need to synchronize it.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • I know JSPs are just Servlets, but am I safe using non-synch collections in JSPs? What about classes used by Servlets? What about coding functions in frameworks like Spring? – Steve Aug 09 '12 at 16:32
  • @Steve - the answer is "it depends". If the objects involved are thread-confined, it is safe. Otherwise, it is too complicated to generalize. – Stephen C Aug 09 '12 at 16:38
  • How do I know if my code can be seen by other threads? I'm not creating any threads intentionally. Are there situations other than Servlets and Swing where that is done for me and that may lead to problems? – Steve Aug 09 '12 at 16:39
  • It is **objects** that are thread confined, not code. And the answer is "by reading and understanding your code". – Stephen C Aug 09 '12 at 16:40