gpt4 book ai didi

java - 使用原子非阻塞方法的单例与同步方法

转载 作者:行者123 更新时间:2023-12-02 09:25:20 25 4
gpt4 key购买 nike

我尝试使用非阻塞原子 boolean API 来生成单例对象而不是同步对象。

我有两个实现

  1. 通过双重锁定和同步关键字
  2. 通过原子非阻塞调用

我相信我们可以通过 Atomic 实现比同步更强大、更好的实现。如果我不正确,请提出建议。还执行一些基本的性能测试,这有利于原子实现而不是同步。

支持

// Lazy Initialization
// Thread-safe
// Performance improvement for corresponding calls, once the object is created

public class Singleton {
private static Singleton instance;

static final AtomicBoolean isInitialized = new AtomicBoolean(false);

private Singleton() {
// private constructor //Thread.sleep(10)

}

// 1st Implementation
// Via Double Locking and Synchronized
public static Singleton getInstance() {
if (instance == null) {
// synchronized block to remove overhead
synchronized (Singleton.class) {
if (instance == null) {
// if instance is null, initialize
instance = new Singleton();
}
}
}
return instance;
}

// 2nd Implementation + Not ThreadSafe with Null Objects.
// Via Atomic Non Blocking Method and avoiding Synchronized
public static Singleton getInstanceViaAtomic() {
if (instance != null)
return instance;

if (isInitialized.compareAndSet(false, true)) {
return instance = new Singleton();
}
return instance;
}

}

更新 @Kayaman 正确识别出上述 impl 不是线程安全的。我修复了下面的一个。

// 2nd Implementation + Thread Safe
// Via Atomic Non Blocking Method and avoiding Synchronized
public static Singleton getInstanceViaAtomic() throws InterruptedException {
while(instance == null) {
if (isInitialized.compareAndSet(false, true)) {
instance = new Singleton();
}
}
return instance;

}

最佳答案

第二个实现不是线程安全的。显示它的一个简单方法是将 Thread.sleep(10); (或更多)放入 Singleton 的构造函数中。

这会导致第一个线程将 isInitialized 设置为 true(而 instance 仍为 null),然后调用 new Singleton( );.

另一个线程会将 instance 视为 null,它不会进入 if block ,因为 boolean 值现在为 true,那么它将返回 instance ,该实例为 null。

因此,竞争条件以 NullPointerException 结尾。

如果我们要强制这个解决方案成为一个可行的解决方案,它必须使用自旋锁,并且可能是这样的(这是早上的代码,所以如果有什么奇怪的,请告诉我):

public static Singleton getInstance() {

// Fast-path when singleton already constructed
if(instance != null)
return instance;

// Spinlock lets the first thread through, others will spin
while(instance == null && !isInitialized.compareAndSet(false, true))
;

// First thread creates the singleton, spun threads will ignore
if(instance == null)
instance = new Singleton();

return instance;
}

此外实例需要是 volatile 以确保可见性。

第一个进入的锁将清除自旋锁,因为即使实例为 null,!compareAndSet 也会返回 false(因为它第一次成功)。

在此之后,任何进入的线程都将保留在自旋锁中,因为 instance == null!compareAndSettrue。当实例构造完成后,由于第一个条件,自旋锁总是会失效。

这基本上是带有自旋锁而不是同步的 DCL,并且我认为上面的代码在任何情况下都不会有用。

关于java - 使用原子非阻塞方法的单例与同步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58380863/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com