Java 帮助检查以下代码,它是线程安全的吗?
构造函数Foo()可能会从多个线程调用。我关心的是私有静态字段“callback”和静态方法“getCallback()” 可以看出,每次调用“getCallback()”时,它都会为静态字段“callback”分配一个新值 我的猜测是,它不是线程安全的,因为关键字static总是附加到类而不是实例,所以这意味着,一个Foo的静态字段“callback”可能会被正在构造另一个Foo()的其他线程覆盖。这是正确的吗 如果我错了,请纠正我。谢谢Java 帮助检查以下代码,它是线程安全的吗?,java,multithreading,static-methods,Java,Multithreading,Static Methods,构造函数Foo()可能会从多个线程调用。我关心的是私有静态字段“callback”和静态方法“getCallback()” 可以看出,每次调用“getCallback()”时,它都会为静态字段“callback”分配一个新值 我的猜测是,它不是线程安全的,因为关键字static总是附加到类而不是实例,所以这意味着,一个Foo的静态字段“callback”可能会被正在构造另一个Foo()的其他线程覆盖。这是正确的吗 如果我错了,请纠正我。谢谢 编辑:我的意图是在类中的某个地方保留“callback
编辑:我的意图是在类中的某个地方保留“callback”,以便以后可以重用它。但这并不容易,因为Foo是从一个类扩展而来的,该类的构造函数要求传递“回调”。当两个线程同时进入
getCallback()
方法时,Foo
的两个实例可能以相同的CallBack
实例结束,其中一个线程向静态字段分配一个新的CallBack
,而另一个线程已经这样做但尚未返回。在这种情况下,最好的解决方法是不使用静态字段,因为它没有任何用途。或者,使getCallback()
同步
但请注意,并非只有
static
关键字才会产生非线程安全的代码。回调将在每次调用Foo()时获得一个新值(即使来自同一线程)。我不太确定您的代码应该做什么(如果您只想初始化静态变量一次(singleton),那么您应该检查getCallback()中的静态变量是否仍然为null-什么是actionCallback?)。要使其线程安全,请使用synchronized。我认为您自己对其进行了完美的总结,但如果没有更多关于您试图实现的目标的详细信息,则很难提出解决问题的建议
一个明显的问题是,
回调
必须是静态的吗?或者,在不破坏类功能的情况下,可以安全地将其作为实例字段吗?它不是线程安全的。尝试以下备选方案:
选项1:这里所有实例共享相同的回调
private static Callback callback;
public Foo()
{
super(getCallback());
}
private static Callback getCallback()
{
callback = new Callback();
return callback;
}
选项2:这里每个实例都有自己的回调
private static final Callback callback = new Callback();
public Foo() {
super(callback);
}
注意,在这两种情况下,尽管构造函数是线程安全的,但整个类的线程安全性取决于回调的实现。如果它具有可变状态,那么您将有潜在的问题。如果回调是不可变的,那么您就有了线程安全性。我知道它已经被回答了,但是为什么还没有被详细说明 如果有两个线程正在调用getCallback()方法,它们可以执行以下行:
我希望这会有所帮助。您正在尝试的被称为单例模式,如果您进行搜索,您可以找到为什么如果可以,通常避免这种模式是一个好主意,但是如果您需要它,您可以执行以下操作
public Foo() {
super(new Callback());
}
或者,如果你需要一个懒惰的单身汉,你可以这样做
private static final Callback CALLBACK= new Callback();
这两种实现都是线程安全的。您希望每个线程一次回调,每个对象一次回调,还是一个真正的单例回调 一些关于如何做不同变体的草图-只是从我的头顶开始,不要把这些太字面化:) 请注意,我假设回调有一个非平凡的构造函数,它可能抛出需要处理的异常,如果它是一个平凡的构造函数,那么您可以将所有这些都简化很多 每个线程一个:
public class Foo {
class CallbackHolder {
static final Callback CALLBACK= new Callback();
}
public static Callback getCallback() {
return CallbackHolder.CALLBACK;
}
public Foo() {
super(getCallback());
}
为了实现完整性,每个对象一次回调:
private final static Callback callback;
static {
callback = new Callback();
}
public Foo()
{
super(getCallback());
}
private static Callback getCallback()
{
return callback;
}
好问题。这些问题很难自己进行逻辑思考,无法编译。actionCallback来自哪里。一般来说,不要通过构造函数初始化静态字段,除非您想引起混淆。对不起,“actionCallback”应该是“callback”。我的意图是在类中的某个地方保留“callback”,以便以后可以重用它。但这并不容易,因为Foo是从一个类扩展而来的,该类的构造函数要求传递“回调”。
private final static Callback callback;
static {
callback = new Callback();
}
public Foo()
{
super(getCallback());
}
private static Callback getCallback()
{
return callback;
}
private Callback callback;
public Foo()
{
super(getCallback());
}
private Callback getCallback()
{
callback = new Callback();
return callback;
}