Java 实例化非最终静态变量是线程安全的吗?
这两个班是一样的吗Java 实例化非最终静态变量是线程安全的吗?,java,multithreading,design-patterns,thread-safety,jvm,Java,Multithreading,Design Patterns,Thread Safety,Jvm,这两个班是一样的吗 public class SingleTone { // yes this is a bug what if i change the class this way // private static SingleTone instance = new SingleTone(); // and empty constructor? private static SingleTone instance; private Single
public class SingleTone {
// yes this is a bug what if i change the class this way
// private static SingleTone instance = new SingleTone();
// and empty constructor?
private static SingleTone instance;
private SingleTone() {
instance = new SingleTone();
}
public static SingleTone getInstance(){
return instance;
}
}
及
构造函数实例化的非最终变量是否存在线程安全问题
问题2:
它们之间有什么区别
private final static SingleTone instance = new SingleTone();
private SingleTone() {
}
这是:
private final static SingleTone instance;
private SingleTone() {
instance = new SingleTone();
}
魁斯顿1号 你的第一个例子不起作用 就像在创建该类型的对象之前调用SingleTone.getInstance()一样,它将返回null 第二个例子很好 问题2 同样的情况,您正在构造函数中设置一个静态字段。这没有意义,因为您不能保证在访问静态字段之前调用了构造函数 您可以这样做:
private final static SingleTone instance;
static {
instance = new SingleTone();
}
这将在第一次加载类时实例化静态字段
回答你的评论 如果您这样做:
private static final SingleTone instance = new SingleTone();
这是线程安全的,就像第一个线程尚未完成初始化类,而另一个线程试图访问它,而另一个线程将阻止它一样
有关更多信息,请参见此问题:这两个选项实际上是相同的(但在这两种情况下都缺少
super()
调用构造函数)
然而,使用私有静态字段实现singleton is Java往往不受欢迎。现在,我将使用枚举
public enum Elvis {
INSTANCE;
private final String[] favoriteSongs =
{ "Hound Dog", "Heartbreak Hotel" };
public void printFavorites() {
System.out.println(Arrays.toString(favoriteSongs));
}
}
若你们想进一步阅读:SingleTone类必须返回一个引用,所以第一个例子是完全错误的 考虑以下过程: 1.类加载由JVM启动 2.类被加载到JVM中。 3.构造函数执行 4.对象创建已完成 公共类单音{ 对于此示例,实例将在1和2之间处于活动状态 私有最终静态单音实例=新单音() } 公共类单音{ 对于这个示例,实例将在3到4之间处于活动状态 私有最终静态单音实例
private SingleTone() {
instance = new SingleTone();
}
public static SingleTone getInstance(){
return instance;
}
}是的,你说得对,如果我用private static SingleTone instance=new SingleTone()的方式重写我的第一个示例会怎么样;并删除构造函数实例!使用final有什么好处!(我正在寻找线程安全问题而不是性能)根据您的评论更新答案谢谢我得到了错误!然而,在我的评论中,我没有使用最终变量,也没有使用最终变量。我更新了答案,请再看一遍,我不确定我是否理解,但是如果您通过私有构造函数限制对字段的访问,并且不提供任何设置字段,那么您就不需要final。ie使用final不会使它更安全,更需要澄清:如果我用private static SingleTone instance=new SingleTone()的方式重写我的第一个示例;并删除构造函数实例!使用final有什么好处!(我寻求的是线程安全问题,而不是性能问题)问题原始版本的两部分都包含bug。而你的“澄清”问题现在是如此混乱,以至于无法回答。。。IMO.可以回答的一点是:有或没有
final
字段实际上是final,因为它保证只分配一次。它是线程安全的,因为赋值发生在类初始化时。我没有注意到问题中的错误。谢谢@cowls,我得到了部分答案,但是我仍然不知道使用静态非最终变量时的线程安全问题。我更新了我的问题,并尽我最大的努力来澄清它。我没有要求实现单音,我知道Enum的方式。
private SingleTone() {
}
public static SingleTone getInstance(){
return instance;
}
private SingleTone() {
instance = new SingleTone();
}
public static SingleTone getInstance(){
return instance;
}