Double check中的易失物质是什么?

use*_*756 1 java algorithm concurrency synchronization

让我们看看经典的双重检查

class Foo {
    private volatile Foo singleton = null;
    public Foo getFooSingleton() {
        if (singleton == null) {
            synchronized(this) {           
                if (singleton == null)
                    singleton = new Foo();
            }
        }
        return singleton;
    }
}
Run Code Online (Sandbox Code Playgroud)

易失性modifire保证在所有线程中都能正确看到"singleton"变量的值.但在当前的例子中我真的需要这个吗?我想不是.所以 - 这就是我看到这个程序以最糟糕的方式运行的方式 - 当一个线程所做的更改被其他人看不到时.

  1. thread one enteres synchronized section并创建singleton
  2. 线程两个enteres同步,同步其当前堆栈值(现在他看到singleton != null),进行第二次检查并退出同步部分.

所以.即使没有挥发性声明,一切都有效,甚至更好=)

axt*_*avt 5

是的,volatile这里需要.

关键是在创建(包括创建对象和执行其构造函数)之间没有内存屏障Foo,并在singleton字段中存储对它的引用,其他线程可以观察到以任意顺序发生的这些操作.特别地,在第一次检查期间,线程2可以观察指向部分构造的对象的参考.请注意,synchronized块在此处无法帮助,因为线程2看到singleton != null并且根本不进入它.

使用volatile确保放置适当的内存屏障(因为Java 5;在以前的版本中,双重检查成语根本无法实现).