简体   繁体   English

像这样初始化后,是否可以避免重复检查锁定中的易失性读取?

[英]Can I avoid the volatile read in double checked locking once initialized like this?

By using a volatile boolean that is read only if the instance is null, can I avoid the default/frequent volatile read once the instance is initailized like so? 通过使用仅当实例为null时才可读的volatile布尔值,是否可以避免实例实例化后的默认/频繁volatile读取? Havent seen anyone recommend double checked locking like this, but seems to avoid volatile reads once fully initialized... Havent看到有人建议像这样进行双重检查锁定,但似乎避免了在完全初始化后进行易失性读取...

public class Singleton {

   private static volatile boolean initialized = false;
   private static Object lock = new Object();
   private static Singleton instance;

      public static Singleton getInstance(){
           if(instance != null) return instance;
           if(!initialized){
                synchronized(lock){
                   if(!initialized){
                       instance = new Singleton();
                       initialized = true;
                   }
                }
           }
           return instance;

       }

} }

No, you cannot. 你不能。 If thread A has reached the synchronized block and is executing the 如果线程A已到达同步块并正在执行

instance = new Singleton();

line, a thread B entering your function could see instance as initialized before thread A has finished constructing the object. 在线程A结束构造对象之前,进入函数的线程B可能会看到instance已初始化。 So you risk having thread B try to work on a partially constructed object. 因此,您冒着使线程B尝试在部分构造的对象上工作的风险。

See the DLCP article for variations and explanations on this pattern. 有关此模式的变体和说明,请参见DLCP文章。

Your optimization attempt is not only premature, but also fruitless, quoting Are volatile variable 'reads' as fast as normal reads? 您的优化尝试不仅过早,而且徒劳无功,引用volatile变量“读取”的速度是否与普通读取一样快? :

On an x86, there is no additional overhead associated with volatile reads. 在x86上, 没有与易失性读取相关的额外开销

If you want lazy instantiation but concerned about performance, use "inner class" approach - it is cleaner and shorter (and a tiny bit more efficient as well). 如果您想要延迟实例化但又担心性能,请使用“内部类”方法-它更简洁,更短(并且效率更高一点)。 Something like that: 像这样:

public class Singleton {

    private static class SingletonHolder {
        private static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }

}

The trick is that instance is created during initialization of the inner class - that will happen when class is first referenced, which is first call to getInstance() . 诀窍是,实例是在内部类的初始化期间创建的-首次引用类时会发生这种情况,这是对getInstance()首次调用。 BTW - avoid such "static" singletons, unless there are truly good reasons to use them. 顺便说一句-除非有充分的理由使用它们,否则请避免使用此类“静态”单身人士。

volatile read is (almost) free on most hardware, volatile write is expensive, though... So why bother? 易失性读取在大多数硬件上(几乎)是免费的,但是易失性写入非常昂贵,但是...为什么要打扰?

The short answer is no. 最简洁的答案是不。 between instance = new Singleton() and initialized = true on a weak memory model where stores can be reordered a reader might see an uninitialized Signleton. 在可以重新排序存储的弱内存模型上,在instance = new Singleton()initialized = true ,读者可以看到未初始化的Signleton。 on x86 and sparc TSO no store-store reorder but on ARM and IA64 it does happen. 在x86和sparc TSO上,没有存储重新排序,但是在ARM和IA64上确实发生了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 非易失性双重检查锁定,可以吗? - Non volatile double checked locking, is it possible? 双重检查锁定没有挥发性 - Double-checked locking without volatile 为什么volatile用于double checked locking - Why is volatile used in double checked locking 如何打破双重检查锁定没有volatile - How to break double checked locking without volatile 仔细检查了锁定的懒惰初始化-我是否需要Map的volatile关键字 - Double checked locking lazy Initialization - Do I need to have volatile keyword for the Map 为什么即使在波动的修复之后,双重检查锁仍然不鼓励? - why is double checked locking still discouraged even after the volatile fix? 在Java中进行双重检查锁定是否需要`volatile`而不是C#? - Is `volatile` required for double-checked locking in Java but not C#? 使用双重检查锁定,在保证之前是否发生了对易失性ConcurrentHashMap的放置? - With double-checked locking, does a put to a volatile ConcurrentHashMap have happens-before guarantee? 双重检查锁定而不使用volatile-keyword并且不同步整个getInstance()方法 - Double checked locking without using volatile-keyword and without synchronizing the entire getInstance() method 单例中的双重检查锁定 - Double Checked Locking in Singleton
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM