title: StringBuilder modified by multiple threads
body: <p>The question I am asking is related to  <a href="https://stackoverflow.com/questions/355089/stringbuilder-and-stringbuffer-in-java">Difference between StringBuilder and StringBuffer</a> but not the same. I want to see what really happens if a StringBuilder is modified by two threads at the same time.</p>
  
  <p>I wrote the following classes:</p>
  
  <pre><code>public class ThreadTester
  {
      public static void main(String[] args) throws InterruptedException
      {
          Runnable threadJob = new MyRunnable();
          Thread myThread = new Thread(threadJob);
          myThread.start();
  
          for (int i = 0; i &lt; 100; i++)
          {
              Thread.sleep(10);
              StringContainer.addToSb("a");
          }
  
          System.out.println("1: " + StringContainer.getSb());
          System.out.println("1 length: " + StringContainer.getSb().length());
      }
  }
  
  public class MyRunnable implements Runnable
  {
      @Override
      public void run()
      {
          for (int i = 0; i &lt; 100; i++)
          {
              try
              {
                  Thread.sleep(10);
              }
              catch (InterruptedException e)
              {
                  e.printStackTrace();
              }
              StringContainer.addToSb("b");
          }
  
          System.out.println("2: " + StringContainer.getSb());
          System.out.println("2 length: " + StringContainer.getSb().length());
      }
  }
  
  public class StringContainer
  {
      private static final StringBuffer sb = new StringBuffer();
  
      public static StringBuffer getSb()
      {
          return sb;
      }
  
      public static void addToSb(String s)
      {
          sb.append(s);
      }
  }
  </code></pre>
  
  <p>Initially I kept a StringBuffer in the StringContainer. Since StringBuffer is thread-safe, at a time, only one thread can append to it, so the output is consistent - either both threads reported the length of the buffer as 200, like:</p>
  
  <pre><code>1: abababababababababbaabababababababbaababababababababababababbabaabbababaabbaababababbababaabbababaabababbaabababbababababaababababababababbababaabbaababbaababababababbaababbababaababbabaabbababababaab
  1 length: 200
  2: abababababababababbaabababababababbaababababababababababababbabaabbababaabbaababababbababaabbababaabababbaabababbababababaababababababababbababaabbaababbaababababababbaababbababaababbabaabbababababaab
  2 length: 200
  </code></pre>
  
  <p>or one of them reported 199 and the other 200, like:</p>
  
  <pre><code>2: abbabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab
  2 length: 199
  1: abbababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa
  1 length: 200
  </code></pre>
  
  <p>The key is that the last thread to complete reports a length of 200.</p>
  
  <p>Now, I changed StringContainer to have a StringBuilder instead of StringBuffer i.e. </p>
  
  <pre><code>public class StringContainer
  {
      private static final StringBuilder sb = new StringBuilder();
  
      public static StringBuilder getSb()
      {
          return sb;
      }
  
      public static void addToSb(String s)
      {
          sb.append(s);
      }
  }
  </code></pre>
  
  <p>I expect some of the writes to be over-written, which is happening. But the contents of the StringBuilder and the lengths do not match sometimes:</p>
  
  <pre><code>1: ababbabababaababbaabbabababababaab
  1 length: 137
  2: ababbabababaababbaabbabababababaab
  2 length: 137
  </code></pre>
  
  <p>As you can see the printed content has only 34 chars, but the length is 137. Why is this happening?</p>
  
  <p>@Extreme Coders - I just did one more test run:</p>
  
  <pre><code>2: ababbabababaabbababaabbababaababaabbaababbaaababbaabbabbabbabababbabababbbabbbbbabababbaabababbabaabaaabaababbaabaababababbaabbbabbbbbababababbababaab
  1: ababbabababaabbababaabbababaababaabbaababbaaababbaabbabbabbabababbabababbbabbbbbabababbaabababbabaabaaabaababbaabaababababbaabbbabbbbbababababbababaab
  1 length: 150
  2 length: 150
  </code></pre>
  
  <p>Java version: 1.6.0_45 and I am using eclipse version: 
  Eclipse Java EE IDE for Web Developers.
  Version: Juno Service Release 2
  Build id: 20130225-0426</p>
  
  <p><b>UPDATE 1:</b> I ran this outside eclipse and now they seem to be matching, but I am getting ArrayIndexOutOfBoundsException sometimes:</p>
  
  <pre><code>$ java -version
  java version "1.6.0_27"
  OpenJDK Runtime Environment (IcedTea6 1.12.5) (6b27-1.12.5-0ubuntu0.12.04.1)
  OpenJDK Server VM (build 20.0-b12, mixed mode)
  
  $ java ThreadTester
  1: ababbbbbabbabababababaababbaabbbaabababbbababbabababbabbababbbbbbabaabaababbbbbbabbbbbaabbaaabbbbaabbbababababbbbabbababab
  1 length: 123
  2: ababbbbbabbabababababaababbaabbbaabababbbababbabababbabbababbbbbbabaabaababbbbbbabbbbbaabbaaabbbbaabbbababababbbbabbababab
  2 length: 123
  
  $ java ThreadTester 
  2: abbabaabbbbbbbbbababbbbbabbbabbbabaaabbbbbbbabababbbbbbbbbabbbbbbbababababbabbbbaabbbaaabbabaaababaaaabaabbaabbbb
  2 length: 115
  1: abbabaabbbbbbbbbababbbbbabbbabbbabaaabbbbbbbabababbbbbbbbbabbbbbbbababababbabbbbaabbbaaabbabaaababaaaabaabbaabbbb
  1 length: 115
  
  $ java ThreadTester 
  Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
      at java.lang.System.arraycopy(Native Method)
      at java.lang.String.getChars(String.java:862)
      at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:408)
      at java.lang.StringBuilder.append(StringBuilder.java:136)
      at StringContainer.addToSb(StringContainer.java:14)
      at ThreadTester.main(ThreadTester.java:14)
  2: abbbbbbababbbbabbbbababbbbaabbabbbaaabbbababbbbabaabaabaabaaabababaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
  2 length: 114
  </code></pre>
  
  <p>The ArrayIndexOutOfBoundsException is also happening when running from eclipse.</p>
  
  <p><b>UPDATE 2:</b>
  There are two problems happening. The first problem of the contents of the StringBuilder not matching the length is happening only in Eclipse and not when I run in command line (at least the 100+ times I ran it on command line it never happened).</p>
  
  <p>The second problem with ArrayIndexOutOfBoundsException should be to do with the internal implementation of StringBuilder class, which keeps an array of chars and does an <code>Arrays.copyOf</code> when it expands the size. But it still beats me how a write is happening before the size is expanded, no matter what the order of execution is.</p>
  
  <p>BTW, I am inclined to agree with @GreyBeardedGeek's answer that this whole exercise is a huge waste of time :-). Sometimes we get to see only the symptoms i.e. the output of some code and wonder what is going wrong. This question declared <i>a priori</i> that two threads are modifying a (very well-known) thread unsafe object.</p>
  
  <p><B>UPDATE 3:</B> Here is the official answer from <a href="https://rads.stackoverflow.com/amzn/click/com/0321349601" rel="nofollow noreferrer" rel="nofollow noreferrer">Java Concurrency in Practice</a> p. 35: </p>
  
  <ul>
  <li><p>In the absence of synchronization, the compiler, processor and
  runtime can do some downright weird things to the order in which
  operations appear to execute. Attempts to reason about the order in
  which memory actions "must" happen in insufficiently synchronized
  multithreaded programs will almost certainly be incorrect. </p></li>
  <li><p>Reasoning about insufficiently synchronized concurrent programs is
  prohibitively difficult.</p></li>
  </ul>
  
  <p>There is also a nice example <code>NoVisibility</code> in the book on p. 34.</p>