gpt4 book ai didi

java - StringBuffer 在线程安全程序的设计中到底是如何工作的?

转载 作者:行者123 更新时间:2023-12-01 23:08:27 25 4
gpt4 key购买 nike

很多人都提到过Java中StringBuffer和StringBuilder的区别。 StringBuffer 包含同步方法。人们会说“如果一个缓冲区被多个线程使用,就使用 StringBuffer”。但是使用StringBuffer真的能保证“线程安全”吗?

最佳答案

嗯,我认为强调 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 并不是设计线程安全应用程序的 Elixir 。更进一步,我想说用于并发的工具和库(例如, 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 附带的锁没有任何帮助。"

希望本文对您有所启发!

关于java - StringBuffer 在线程安全程序的设计中到底是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22412189/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com