Java StringBuilder 和线程安全
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/631645/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java StringBuilder and Thread Safety
提问by Ben
I am building up a String out of multiple pieces and want to use either StringBufferor StringBuilderto do so. From the Java 5 docs, I see that StringBuilderis preferred when possible, with the caveat that
我正在构建一个由多个部分组成的字符串,并且想要使用StringBuffer或StringBuilder这样做。从 Java 5 文档中,我认为StringBuilder在可能的情况下是首选的,但需要注意的是
Instances of
StringBuilderare not safe for use by multiple threads.
的实例
StringBuilder供多线程使用是不安全的。
From this statement, I understand that I should not have a single StringBuilderinstance shared by multiple threads. But what about this case:
从这个声明中,我明白我不应该让StringBuilder多个线程共享一个实例。但是这个案例呢:
//Is this safe?
//foo() is called simultaneously by multiple threads
String foo(String a, String b) {
return new StringBuilder(a).append(b).toString();
}
Here there could be multiple threads in the function at the same time, using the StringBuilderclass at the same time (eg, concurrent access of static variables, if there are any), but each thread would have its own separate instance of StringBuilder. From the documentation, I can not quite decide whether this counts as use by multiple threads or not.
在这里,函数中可能有多个线程同时使用StringBuilder类(例如,静态变量的并发访问,如果有的话),但是每个线程都有自己单独的StringBuilder. 从文档中,我不能完全确定这是否算作被多线程使用。
回答by Michael Myers
That's perfectly fine. Local variables have no problems with thread safety as long as they don't access or mutate instance or class variables.
那完全没问题。局部变量在线程安全方面没有问题,只要它们不访问或改变实例或类变量。
回答by Kip
Yes, that is safe, because the StringBuilder object is used only locally (each thread calling foo() will generate its own StringBuilder).
是的,这是安全的,因为 StringBuilder 对象仅在本地使用(调用 foo() 的每个线程将生成自己的 StringBuilder)。
You should also note that the code you posted is practically identical to the bytecode generated by this:
您还应该注意,您发布的代码实际上与由此生成的字节码相同:
String foo(String a, String b) {
return a + b;
}
回答by TofuBeer
The code you have is safe.
您拥有的代码是安全的。
This code is not.
这段代码不是。
public class Foo
{
// safe
private final static StringBuilder builder;
public static void foo()
{
// safe
builder = new StringBuilder();
}
public static void foo(final String a)
{
// unsafe
builder.append(a);
}
public synchronized void bar(final String a)
{
// safe
builder.append(a);
}
}
Local variables that only make use of local data do not have threadsafe issues. You can only have threadsafe issues once you start dealing with data that is visible at the class or instance method/variable level.
仅使用本地数据的本地变量没有线程安全问题。一旦开始处理在类或实例方法/变量级别可见的数据,您只会遇到线程安全问题。
回答by Bill K
Agree with the other answers--just a note.
同意其他答案——只是一个注释。
If there was a case where StringBuffer was being used by multiple threads, it's probably a completely broken use case because it would mean a single string was being built up in a quasi-random order, so it wouldn't make sense to make StringBuffer thread safe.
如果存在多个线程使用 StringBuffer 的情况,这可能是一个完全破坏的用例,因为这意味着以准随机顺序构建单个字符串,因此使 StringBuffer 线程没有意义安全的。
回答by ReneS
I am not sure if this code is needed, because Java picks the StringBuilder automatically I guess. If you do not have a performance problem, go with a + b.
我不确定是否需要这段代码,因为我猜 Java 会自动选择 StringBuilder。如果您没有性能问题,请使用 a + b。
In case of a performance need, try that:
如果需要性能,请尝试:
return new StringBuilder(
a.length() + b.length()).append(a).append(b).toString();
It correctly sizes the buffer and prevents the VM from resizing it and creating garbage to collect on the way.
它正确调整缓冲区大小,并防止 VM 调整大小并在途中创建要收集的垃圾。

