如果线程在java中重新分配变量会发生什么?

时间:2017-06-05 12:50:50

标签: java spring multithreading

我想知道以下(人为的)示例是否是线程安全的:

public class SpringSingleton
{

    private MyObject _myObject = new MyObject("hello");

    public void useObject()
    {
        _myObject.doSomethingCool();
    }

    public void changeObject()
    {
        _myObject = new MyObject("goodbye");
    }

    public static void main(String[] args)
    {
        // Have multiple threads, some using and some changing the object
    }

}

我的主要问题是:当一个线程试图在另一个线程试图调用useObject()的同时调用changeObject()时会发生什么?

2 个答案:

答案 0 :(得分:2)

分配引用是一种原子操作。您永远不会看到半分配的参考。因此,调用doSomethingCool()方法的线程将在旧引用或新引用上调用它。

但这并不能使代码线程安全。您还可能遇到可见性问题:即使线程已经编写了新引用,读取引用的线程也可能会看到旧的引用。要解决该问题,您需要使字段变为volatile,或将其包装到AtomicReference中,或者同步对字段的所有访问。

另请注意,如果您将代码更改为

_myObject.doSomethingCool();
_myObject.doSomethingElse();

然后你会遇到另一个问题:第一次调用可能是在旧对象上进行的,第二次是在新对象上进行的。如果在这两个调用之间需要一致性,那么这两个调用以及与_myObject的每次其他交互都应该被包装到一个synchronized块中(使用相同的锁)。

答案 1 :(得分:0)

如果一个线程试图同时调用useObject()另一个线程试图调用changeObject(),那么该行为是不确定的,调用useObject()的线程可能会看到旧的或新的价值。

是否安全"取决于你想要的行为。
在很短的时间内,您的代码可能无关紧要。