【问题标题】:Is thread safe calling outer class variable?线程安全调用外部类变量吗?
【发布时间】:2018-02-26 23:36:00
【问题描述】:
public class Status {

    private Scheduler scheduler;
    private volatile Boolean lastResult;

    public Status() {
        scheduler = new Scheduler();
        scheduler.everyTenSeconds(new Action());
    }


    public boolean isSth()  {
        if (lastResult != null && lastResult) {
            return lastResult;
        } else {
            return checkSth();
        }
    }


    private boolean checkSth() throws SomeException {
        // checking sth
    }

    private class Action implements Runnable {

        @Override
        public void run() {
            try {
                lastResult = checkSth();
            } catch (SomeException e) {
                lastResult = false;

            }

        }
    }
}

调用外部类变量是线程安全的吗?最后一个结果是 lastResult 但在调用 isSth() 时 lastResult 始终为空。尽管 run 被调用了两次。

【问题讨论】:

  • 您能否分享您正在运行以产生您描述的问题的示例代码?
  • 对不起,我不明白,你是想调用具有外部类作为变量的线程还是具有外部类变量的线程或调用外部类的线程

标签: java multithreading inner-classes outer-classes


【解决方案1】:

调用外部类变量是线程安全的吗?

一般来说,它既不是线程安全的,也不是线程安全的。线程安全取决于您实际执行的操作。

而且...严格来说是正确的...您不能调用变量:

  • 您可以读取变量的值
  • 如果变量的值是一个对象,那么您可以调用该对象的实例方法

在您的示例中,代码正在执行涉及 volatile 的操作序列。对 volatile 的单个读取或写入操作是原子的,并且在 Java 内存模型方面具有明确定义的属性。但是,一系列操作不是原子的,而且 JMM 属性很复杂。

长话短说,您的代码正在对lastResult 执行一系列读写操作,并且不是线程安全的。


但是,尽管如此,我不明白您的代码如何/为什么始终将lastResult 设置为null。我怀疑这与您使用此代码的方式有关。我们真的需要一个 MCVE;即,我们可以运行一个完整可执行示例来查看您所看到的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多