Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何安全地发布StringBuffer?_Java_Multithreading_Safe Publication - Fatal编程技术网

Java 如何安全地发布StringBuffer?

Java 如何安全地发布StringBuffer?,java,multithreading,safe-publication,Java,Multithreading,Safe Publication,因为它是线程安全的,所以可以安全地发布它。考虑“ StringBuffer > /COD>())的公共构造函数: 其中,super(16)指定了这个: AbstractStringBuilder(int capacity) { value = new char[capacity]; } 其中值声明为 char[] value; 问题:如何安全发布StringBuffer 我有以下课程: public class Holder{ public final StringBuff

因为它是线程安全的,所以可以安全地发布它。考虑“<代码> StringBuffer > /COD>())的公共构造函数:

其中,
super(16)
指定了这个:

AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}
其中值声明为

char[] value;
问题:如何安全发布
StringBuffer

我有以下课程:

public class Holder{
     public final StringBuffer sb = new StringBuffer();
}
它能被认为是安全的出版物吗我认为,它不能。

final
保证我们将看到引用的新值
sb
。但是在
AbstractStringBuilder(int capacity)
中写入
sb
的内部状态是不同步的。因此,在顺序之前没有发生
,这反过来意味着在调用
sb.append(2)时从
读取和写入构造函数中的
都是快速的

你能帮助理解这一点吗?也许我错过了什么

你能帮助理解这一点吗?也许我错过了什么

AFAIR after
JSR-133
可以保证初始化的类的
final
字段在实例化过程中不受争用条件的影响,并且只有正确的值在初始化后才会公开

upd:通过

在新的内存模型下,构造函数中最后一个字段的写入和另一个线程中对该对象的共享引用的初始加载之间存在类似于“先发生后发生”的关系。当构造函数完成时,对最终字段(以及通过这些最终字段间接访问的变量)的所有写入都将被“冻结”,并且任何在冻结后获得对该对象的引用的线程都将确保看到所有冻结字段的冻结值。初始化最终字段的写入将不会在与构造函数关联的冻结后使用操作重新排序

IMHO您的问题(以及并发理解)非常好,因为它不是一个明显的语言/平台设计特性,并且只在JavaSE5.0中修复了它

多线程使用字符串缓冲区是安全的。这些方法在必要时进行同步,以便任何特定实例上的所有操作的行为就像它们以某种顺序发生一样,该顺序与所涉及的每个线程进行的方法调用的顺序一致


这应该是足够的保证。

创建
sb
的实例变量是线程安全的,因为它是在创建
Holder
的实例的同时完成的

它是线程安全的原因是它是一个实例变量,线程1无法开始构造
Holder
(并通过关联创建一个新的
StringBuffer
)的实例,然后第二个线程跳入并开始运行同一实例的构造函数

也就是说,如果您的代码有两个线程,两个线程都遇到了行

Holder h = new Holder();

您将得到两个单独的Holder实例,然后一个race分配给
h
,这是另一个问题。

您的意思是
sb
是一个实例变量,还是应该是静态的?如果您想要一个文本/字符串的线程安全提供程序,并且该文本/字符串有时会发生变化,请使用。StringBuffer用于并发附加到它,这是一个罕见的用例。@Paolo不,它正是一个实例varialbe。静态初始化是在初始化一个类时发生的,该类需要JVM间的锁定,以确保内存的一致性。我认为您对这里的安全性和不安全性感到困惑。构造函数在分配引用之前就已经完成了,在这方面有一个例子:如果你可以看到引用,那么你也可以看到构造函数中发生的一切。唯一不安全的做法是将
这个
从构造函数泄漏到其他地方,而这在
StringBuilder
@JoopEggen中不会发生。问题不在于找到另一种方法。我只是想了解使用StringBuffer是否安全。正确的引用值,是的。但对象的状态引用如何?是的,您上次更新解释了一切。谢谢。所以,如果没有最后的修改,它将不会被认为是安全的出版物。对吧?对。没有
final
在当前JMM下是不安全的。
Holder h = new Holder();