[英]Is this Singleton a thread-safe one?
基于这个主题 ,我提出了一个有趣的Singleton模式版本,该实现基于AtomicIntegers。
问题是:
volatile
修饰符作为实例变量吗? public class StrangeSingleton
{
private StrangeSingleton() {};
private static volatile Object instance;
private static AtomicInteger initCounter = new AtomicInteger();
private static AtomicInteger readyCounter = new AtomicInteger();
static Object getInstance()
{
if (initCounter.incrementAndGet() == 1)
{
instance = new Object();
readyCounter.incrementAndGet();
return instance;
}
else if (readyCounter.get() == 1)
{
return instance;
}
else
{
//initialization not complete yet.
//write here some logic you want:
//sleep for 5s and try one more time,
//or throw Exception, or return null..
return null;
}
}
}
更新:添加了私有构造函数,但它不是重点。
这个实现是正确的和线程安全的,通常可以使用Atomic Variables进行线程同步和管理吗?
但它通常更加复杂和CPU密集,因为您需要忙着等待快速响应变化。
附加问题:如果这个实现是线程安全的,我真的需要一个volatile修饰符作为实例变量吗?
在这种情况下,您不会这样做,因为AtomicInteger包含易失性字段,这将确保正确发生之前/发生后行为。
当然你可以使用一个线程安全且更简单的枚举;)
enum Singleton {
INSTANCE;
}
这个实现是正确的和线程安全的,通常可以使用Atomic Variables进行线程同步和管理吗?
是的,但对于readyCounter
变量,您应该使用CountDownLatch ,如下所示:
private static AtomicInteger initCounter = new AtomicInteger();
private static CountDownLatch readyCounter = new CountDownLatch(1);
static Object getInstance()
{
if (initCounter.incrementAndGet() == 1)
{
try {
instance = new Object();
return instance;
} finally {
readyCounter.countDown();
}
}
else
{
readyCounter.await();
return instance;
}
}
调用await()也可以解决初始化竞争条件。 (我还添加了一个try-finally块来避免构造函数异常死锁。)
附加问题:如果这个实现是线程安全的,我真的需要一个volatile修饰符作为实例变量吗?
不,如果在访问实例变量之前调用相关的AtomicInteger
或CountDownLatch
函数,则不会。 在文档中寻找发生的事情 。
线程T1可以挂在instance = new Object();
, T2将会触及else{}
块,因为readyCounter
尚未增加。 由于初始化已经完成,Thtat不太正确,落后的是状态簿记
我宁愿在你的getInstance()
方法中做一个synchronized
块。 这就足够了。 你不需要这些奇怪的计数器,这些计数器也不像@David注意到的那么安全。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.