Как StringBuffer действительно работает при разработке многопоточных программ?

Многие люди упоминали, что разница между StringBuffer и StringBuilder в Java. StringBuffer содержит синхронизированные методы. И люди говорят что-то вроде "если буфер используется многими потоками, используйте StringBuffer". Но действительно ли использование StringBuffer гарантирует "безопасность потоков"?

1 ответ

Ну, я думаю, что важно выделить некоторые фактические варианты использования StringBuffer. Для этого я разработал простую программу, иллюстрирующую, как StringBuffer может превзойти StringBuilder в достижении безопасности потоков.

/**
 * Run this program a couple of times. We see that the StringBuilder does not
 * give us reliable results because its methods are not thread-safe as compared
 * to StringBuffer.
 * 
 * For example, the single append in StringBuffer is thread-safe, i.e.
 * only one thread can call append() at any time and would finish writing
 * back to memory one at a time. In contrast, the append() in the StringBuilder 
 * class can be called concurrently by many threads, so the final size of the 
 * StringBuilder is sometimes less than expected.
 * 
 */
public class StringBufferVSStringBuilder {

    public static void main(String[] args) throws InterruptedException {

        int n = 10; 

        //*************************String Builder Test*******************************//
        StringBuilder sb = new StringBuilder();
        StringBuilderTest[] builderThreads = new StringBuilderTest[n];
        for (int i = 0; i < n; i++) {
            builderThreads[i] = new StringBuilderTest(sb);
        }
        for (int i = 0; i < n; i++) {
            builderThreads[i].start();
        }
        for (int i = 0; i < n; i++) {
            builderThreads[i].join();
        }
        System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());

        //*************************String Buffer Test*******************************//

        StringBuffer sb2 = new StringBuffer();
        StringBufferTest[] bufferThreads = new StringBufferTest[n];
        for (int i = 0; i < n; i++) {
            bufferThreads[i] = new StringBufferTest(sb2);
        }
        for (int i = 0; i < n; i++) {
            bufferThreads[i].start();
        }
        for (int i = 0; i < n; i++) {
            bufferThreads[i].join();
        }
        System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());

    }

}

// Every run would attempt to append 100 "A"s to the StringBuilder.
class StringBuilderTest extends Thread {

    StringBuilder sb;

    public StringBuilderTest (StringBuilder sb) {
        this.sb = sb;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sb.append("A");
        }

    }
}


//Every run would attempt to append 100 "A"s to the StringBuffer.
class StringBufferTest extends Thread {

    StringBuffer sb2;

    public StringBufferTest (StringBuffer sb2) {
        this.sb2 = sb2;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sb2.append("A");
        }

    }
}

Однако, как и многие другие, StringBuffer - не чудодейственное средство для разработки поточно-ориентированных приложений. Чтобы пойти еще дальше, я бы сказал, что инструменты и библиотеки для параллелизма (например, Vector) должны быть хорошо поняты и соответствующим образом реализованы, и мы не должны делать простых предположений об использовании "поточно-ориентированных" библиотек.

http://jeremymanson.blogspot.sg/2008/08/dont-use-stringbuffer.html

Пример Джереми иллюстрирует суть, и я цитирую:

Thread 1:
sb.append("a");

Thread 2:
sb.append("b");

Thread 3:
join 1,2
print(sb.toString());

"Конечно, это" потокобезопасный ", в том смысле, что нет гонок данных (которые в основном являются параллельными доступами без адекватной синхронизации). Но вы не знаете, какой поток 3 напечатает: "ab"или"ba". Мне нужно было бы ввести больше синхронизации, чтобы это дало ощутимый результат. Блокировки, которые идут с StringBuffer, ничего не помогли ".

Я надеюсь, что это полезно для вас!

Другие вопросы по тегам