关于实例变量初始化的线程安全性

时间:2009-10-14 20:17:49

标签: java thread-safety

我看到这个实例变量初始化的习惯用法很多

public class Test{
    private Long l = 1l;
    private MyClass mc = new MyClass();

    public Test(){}
    ...
 }

但我更喜欢

public class Test{
    private Long l;
    private MyClass mc;

    public Test(){
        l = 1l;
        mc = new MyClass();
    }
    ...
}

考虑到这些是非最终变量,在线程安全方面,2种方法是等价的还是比其他方法“更”正确?

6 个答案:

答案 0 :(得分:6)

线程安全不是问题,因为这在构造阶段发生,并且两个线程不能构造相同的对象。好吧,如果你让this从构造函数中逃脱,那么另一个线程可能在构造期间访问该对象,但你真的不应该这样做。功能方面,两个选项是相同的,所以即使存在线程安全问题,它们也会以同样的方式影响。

如果你需要进行一些无法在初始化程序中完成的计算,那么第一个在声明中初始化字段的选项并不总是可行的(即便如此,如果你这样做,你可以将初始化保留在构造函数之外)但是在初始化程序块中。但是,如果任何一种方式都可行,那么它纯粹是一种风格问题,我不认为Java程序员有明显的偏好,所以请选择对你来说更好的方式。

答案 1 :(得分:1)

由于您的变量是实例变量,而不是类变量,因此在初始化期间使用任一方法都没有线程安全问题。我敢肯定,如果有Java标准推荐的最佳实践,其他人也会参与进来。

答案 2 :(得分:1)

我认为这是个人偏好和项目编码标准的问题。

确保只在一个地方(构造函数或内联)初始化变量。

在构造函数中完成初始化工作可以为您提供更好的异常处理空间。

答案 3 :(得分:1)

它们都不是线程安全的。如果线程A构造对象,则线程B可能会或可能不会观察到未完全初始化的Test对象或MyClass对象。构造函数退出后的可见性保证仅适用于最终字段。

请参阅http://pveentjer.wordpress.com/2007/03/18/immutability-doesnt-guarantee-thread-safety/

答案 4 :(得分:0)

就线程安全而言,它们是等效的。两者都需要执行相同的指令,如果您更喜欢第二个(我根据您的喜好与您达成一致),那么我会使用它。如果您希望构造函数周围的线程安全,则需要围绕构造函数调用进行同步调用。

答案 5 :(得分:0)

我不确定是否早些回答。但是,我对以下情况有疑问:

我试图创建一个@Component类,其中有一个实例变量。现在,我想为每个请求创建一个实例变量的新对象。我不确定哪种方法是正确的?

--kubelet-extra-args --node-labels=alabel=foo,another=bar