因为StringBuffer是线程安全的,所以它可以安全地发布。考虑StringBuffer ( 资料来源 )的公共构造函数:
public StringBuffer() {
super(16);
}其中super(16)指定了这个:
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}声明为
char[] value;问题:如何安全地发布StringBuffer?
我有以下课程:
public class Holder{
public final StringBuffer sb = new StringBuffer();
}它能被认为是安全的出版物吗?我想它不能。
final保证我们将看到引用sb的新值。但是在sb内部写入AbstractStringBuilder(int capacity)的内部状态是不同步的,因此不存在happens-before顺序,这就意味着在调用sb.append(2);时发生从value读取,而在构造函数中写入value则是动态的。
你能帮我理解这件事吗?也许我错过了什么..。
发布于 2016-04-06 10:09:16
你能帮我理解这件事吗?也许我错过了什么..。
在JSR-133之后,保证在实例化过程中初始化的类的final字段在实例化过程中不存在争用条件,并且在init之后只公开正确的值。
upd:通过布赖恩·戈茨实现的
在新的内存模型下,在构造函数中写入最终字段与在另一个线程中对该对象的共享引用的初始加载之间存在类似的情况。当构造函数完成时,对最终字段的所有写入(以及通过这些最终字段可以间接访问的变量)都变成“冻结”,任何在冻结后获得对该对象的引用的线程都保证看到所有冻结字段的冻结值。初始化最终字段的写入将不会与与构造函数关联的冻结后的操作重新排序。
你的问题(以及并发性理解)非常好,因为它不是一个明显的语言/平台设计特性,它只在Java 5.0中得到修正
发布于 2016-04-06 10:12:44
请参阅StringBuffer的javadoc。
字符串缓冲区对于多个线程使用是安全的。这些方法在必要时是同步的,以便使对任何特定实例的所有操作表现得好像它们以某种串行顺序发生一样,该顺序与所涉及的每个单独线程进行的方法调用顺序一致。
这应该是充分的保证。
发布于 2016-04-06 10:12:51
创建sb实例变量是线程安全的,因为它是在创建Holder实例的同时完成的。
线程安全的原因是它是一个实例变量,线程1无法开始构造Holder的实例(并通过关联一个新的StringBuffer),然后第二个线程跳入并开始运行同一个实例的构造函数。
也就是说,如果您的代码有两个线程,这两个线程都跨越了行。
Holder h = new Holder();最后您将得到Holder的两个单独的实例,然后为其分配给h,这是一个不同的问题。
https://stackoverflow.com/questions/36447710
复制相似问题