private static Callback callback;
public Foo()
{
super(getCallback());
}
private static Callback getCallback()
{
callback = new Callback();
return callback;
}
可以从多个线程调用构造函数Foo()。我关心的是私有静态字段'callback'和静态方法'getCallback()'。
可以看出,每次调用'getCallback()'时,它都会为静态字段'callback'分配一个新值。
我的猜测是不是线程安全的,因为关键字 static 总是附加到类而不是实例,这意味着,静态字段'回调'一个Foo可能会被构造另一个Foo()的其他线程覆盖。这是对的吗?
如果我错了,请纠正我。谢谢!
编辑:我的目的是在课堂的某个地方保留'回调',以便我以后可以重复使用它。但这并不容易,因为Foo从一个具有构造函数强制“回调”的类扩展而来。
答案 0 :(得分:6)
是的,你是对的。当两个线程同时进入Foo
方法并且一个新的CallBack
分配给静态字段时,getCallback()
的两个实例可能会以相同的CallBack
实例结束另一个已经完成了这个但尚未返回。在这种情况下,最好的解决方法是不要使用静态字段,因为它没有用处。或者,将getCallback()
同步。
但请注意,不为true,只有static
关键字会产生非线程安全的代码。
答案 1 :(得分:5)
这不是线程安全的。尝试以下替代方案:
选项1:此处所有实例共享相同的回调
private static final Callback callback = new Callback();
public Foo() {
super(callback);
}
选项2:此处每个实例都有自己的回调
public Foo() {
super(new Callback());
}
请注意,在这两种情况下,尽管构造函数是线程安全的,但整个类的线程安全性取决于Callback的实现。如果它具有可变状态,那么你将有潜在的问题。如果Callback是不可变的,那么你就有线程安全性。
答案 2 :(得分:3)
每次调用Foo()时,回调都会获得一个新值(即使是来自同一个线程)。我不太确定你的代码应该做什么(如果你只想初始化静态变量一次(单例),你应该检查它是否仍然在getCallback()中 - 并且什么是actionCallback?)。为了使其成为线程安全的,请使用synchronized。
答案 3 :(得分:2)
我认为你自己总结得很完美,但如果没有更多关于你想要达到的目标的详细信息,提出解决问题的建议将会非常棘手。
一个显而易见的问题是,callback
必须是静态的吗?或者你可以安全地使它成为一个实例字段而不破坏你的类的功能吗?
答案 4 :(得分:2)
我知道它已被回答,但其原因尚未详细说明。
两个线程正在调用getCallback()方法,它们可以按如下方式执行这些行:
在这种情况下,(2.)生成的回调将在(3.)和(4。)中返回
解决方案似乎是问为什么回调定义为静态,如果它特定于实例而不是类。
我希望有所帮助。
答案 5 :(得分:1)
你要做的事情被称为单身人士模式,如果你进行搜索,你可以找出为什么通常一个好主意,如果你可以避免这种模式,但是如果你需要它,你可以做到以下几点。 / p>
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());
}
两种实现都是线程安全的。
答案 6 :(得分:1)
你想要每个线程一个回调,每个对象一个回调,还是一个真正的Singleton?
关于如何做出不同变体的一些草图 - 仅仅从头顶开始,不要太过于字面意思:)
请注意,我假设Callback有一个非常重要的构造函数可能会抛出需要处理的异常,如果它是一个简单的构造函数,你可以简化所有这些。
每个帖子一个:
private static ThreadLocal<Callback> callback;
public Foo()
{
super(getCallback());
}
private static Callback getCallback()
{
if ( callback.get() == null )
callback.set(new Callback());
return callback.get();
}
所有线程的单一回调:
private final static Callback callback;
static {
callback = new Callback();
}
public Foo()
{
super(getCallback());
}
private static Callback getCallback()
{
return callback;
}
并且,对于completness,每个对象一次回调:
private Callback callback;
public Foo()
{
super(getCallback());
}
private Callback getCallback()
{
callback = new Callback();
return callback;
}