【问题标题】:What happens if a thread re-assigns a variable in java?如果一个线程在java中重新分配一个变量会发生什么?
【发布时间】:2017-06-05 12:50:50
【问题描述】:

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

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() 会发生什么?

【问题讨论】:

    标签: java spring multithreading


    【解决方案1】:

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      它是否“安全”取决于您想要的行为。
      在短时间内,它看到的值可能对您的代码无关紧要。

      【讨论】:

        猜你喜欢
        • 2012-06-23
        • 1970-01-01
        • 1970-01-01
        • 2011-06-04
        • 2013-02-24
        • 1970-01-01
        • 1970-01-01
        • 2019-11-02
        • 1970-01-01
        相关资源
        最近更新 更多