无锁和无等待的线程安全延迟初始化

Ale*_*you 27 java multithreading lock-free lazy-initialization wait-free

要执行无锁和无等待的延迟初始化,请执行以下操作:

private AtomicReference<Foo> instance = new AtomicReference<>(null);  

public Foo getInstance() {
   Foo foo = instance.get();
   if (foo == null) {
       foo = new Foo();                       // create and initialize actual instance
       if (instance.compareAndSet(null, foo)) // CAS succeeded
           return foo;
       else                                   // CAS failed: other thread set an object 
           return instance.get();             
   } else {
       return foo;
   }
}
Run Code Online (Sandbox Code Playgroud)

除了一件事之外,它的效果非常好:如果两个线程看到实例null,它们都会创建一个新对象,只有一个幸运的是通过CAS操作设置它,这会浪费资源.

有没有人建议另一种无延迟初始化模式,这会降低两个并发线程创建两个昂贵对象的可能性?

Joh*_*int 22

如果你想要真正的锁定自由,你将不得不做一些旋转.您可以拥有一个线程'获胜'创建权,但其他人必须旋转直到它准备就绪.

private AtomicBoolean canWrite = new AtomicBoolean(false);  
private volatile Foo foo; 
public Foo getInstance() {
   while (foo == null) {
       if(canWrite.compareAndSet(false, true)){
           foo = new Foo();
       }
   }
   return foo;
}
Run Code Online (Sandbox Code Playgroud)

这显然存在繁忙旋转的问题(你可以在那里放一个睡眠或产量),但我可能仍然会建议按需初始化.

  • 在我的示例中,不知道非实例化线程的操作需要多长时间.在实践中它显然不会很长,但是如果不知道线程将旋转多少次,我们就会失去等待的属性.这就是我们如何在无障碍,无锁和无等待之间进行推理. (5认同)
  • 请阅读http://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom.在谈论并发算法时,无等待具有特定含义.也就是说,如果保证操作在有限数量的步骤中完成,则并发算法是无等待的.在OP的示例中,最大步数为2. (2认同)