java匿名内部类实现Runnable和共享外部类对象是否是线程安全的?

时间:2017-05-12 15:51:54

标签: java multithreading thread-safety memory-visibility

public class Main {

    public static void main(String[] args) {
        Status status = new Status();
        new Thread(new Runnable() {
            @Override
            public void run() {
                status.setStatus(true);
            }
        }).start();
    }
}

class Status {
    boolean status = false;
    public void setStatus(boolean status) {
        this.status = status;
    }
    public boolean getStatus() {return status;}
}

如图所示,创建线程共享主线程状态对象。我认为它不是线程安全的,因为cpu缓存,主线程和创建线程加载状态对象到自己的缓存,在创建时-thread call' setStatus'方法它只更新其缓存数据,主线程现在无法看到更新的数据。所以它需要同步。我理解正确吗?

1 个答案:

答案 0 :(得分:3)

有关先发条件的规则,请参阅jls 17.4.5。

在启动线程中的任何操作之前发生启动调用。因此,新线程将在主线程上看到状态对象。

但是状态的更改并不保证对主线程可见。如果主线程加入到新线程中,那么before-before规则将适用,并且一旦新线程完成,更改将可见。如果您希望在不需要新线程完成的情况下看到更改,则可以使布尔值变为volatile或将其类型更改为 的AtomicBoolean。或者将synchronized关键字放在setter和getter上。

请注意,JVM并非要求不要将其显示,因此不需要。 Ymmv取决于jvm的实现。

所以我认为你的理解是正确的。