为了简单起见,我保留了其余的实现,因为它与这里无关。考虑现代 C++ 设计中描述的双重检查查找的经典实现。
Singleton& Singleton::Instance()
{
if(!pInstance_)
{
Guard myGuard(lock_);
if (!pInstance_)
{
pInstance_ = new Singleton;
}
}
return *pInstance_;
}
Run Code Online (Sandbox Code Playgroud)
在这里,作者坚持我们要避免竞争条件。但我读过一篇文章,不幸的是我不太记得了,其中描述了以下流程。
在那篇文章中,作者指出,技巧是可以在线 pInstance_ = new Singleton;分配内存,并将其分配给 pInstance,以便在该内存上调用构造函数。
依靠标准或其他可靠来源,任何人都可以确认或否认此流程的可能性或正确性吗?谢谢!
我正在查看我们的应用程序中的一些代码,我认为可能会遇到" 双重检查锁定 "的情况.我写了一些与我们的工作类似的示例代码.
任何人都可以看到这是如何经历双重检查锁定?或者这样安全吗?
class Foo {
private Helper helper = null;
public Helper getHelper() {
Helper result;
synchronized(this) {
result = helper;
}
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
}
Run Code Online (Sandbox Code Playgroud)
从wiki借来的基本代码.
我一直在阅读很多关于Singleton在线的文章,但大多数文章只展示了创建简单对象并正确锁定以确保线程安全而没有竞争条件.
简单到足以演示,我在那里放了一个文件记录方法.它将适用于10-20个并发线程,但是当我尝试100个线程时,它将失败,因为"进程无法访问该文件,因为它正被另一个进程使用".
public class Logger
{
private string _path = "c:\\temp\\MyTestLog.txt";
// Singleton with padlock for DCL
private volatile static Logger _instance;
private static readonly object _padLock = new Object();
// Singleton
public static Logger Instance()
{
// Implement Double Check Locking (MSDN - Thread-safe)
if (_instance == null)
{
lock (_padLock)
{
if (_instance == null)
_instance = new Logger();
}
}
return _instance;
}
// Simple WriteLog
public void WriteLog(string text, out bool result)
{
try
{
// …Run Code Online (Sandbox Code Playgroud) 我在我的CF应用程序中使用了双重检查锁定的版本(在我知道双重检查锁定之前).
基本上,我检查一个物体的存在.如果它不存在,我锁定(通常使用命名锁),在我尝试创建对象之前,我再次检查是否存在.我认为这是一种简洁的方法来阻止创建多个对象并停止系统中的过度锁定.
这似乎有效,因为没有过多的锁定,并且不会创建对象重复项.但是,我最近了解到Double Checked Locking在Java中不起作用,我不知道的是CF是否适用,因为CF线程和锁与本机Java线程和锁不完全相同.
我编写了一个Java ReadWriteLock,读者使用双重检查锁定来获取写锁定.这是不安全的(对于具有延迟实例化的DCL的情况)?
import java.util.concurrent.atomic.AtomicInteger;
public class DCLRWLock {
private boolean readerAcquiringWriteLock = false;
private boolean writerLock = false;
private AtomicInteger numReaders = new AtomicInteger();
public void readerAcquire() throws InterruptedException {
while (!nzAndIncrement(numReaders)) {
synchronized (this) {
if (numReaders.get() != 0)
continue;
if (readerAcquiringWriteLock) {
do {
wait();
} while (readerAcquiringWriteLock);
} else {
readerAcquiringWriteLock = true;
writerAcquire();
readerAcquiringWriteLock = false;
assert numReaders.get() == 0;
numReaders.set(1);
notifyAll();
break;
}
}
}
}
public void readerRelease() {
if (numReaders.decrementAndGet() == 0)
writerRelease(); …Run Code Online (Sandbox Code Playgroud) java atomic thread-safety readwritelock double-checked-locking