单身类的通常模式就像
static Foo &getInst()
{
static Foo *inst = NULL;
if(inst == NULL)
inst = new Foo(...);
return *inst;
}
Run Code Online (Sandbox Code Playgroud)
但是,我的理解是这个解决方案不是线程安全的,因为1)Foo的构造函数可能被多次调用(可能或可能不重要)和2)inst在返回到不同的线程之前可能没有完全构造.
一种解决方案是围绕整个方法包装一个互斥锁,但是在我真正需要它之后很长时间我就要付出同步开销.另一种选择是
static Foo &getInst()
{
static Foo *inst = NULL;
if(inst == NULL)
{
pthread_mutex_lock(&mutex);
if(inst == NULL)
inst = new Foo(...);
pthread_mutex_unlock(&mutex);
}
return *inst;
}
Run Code Online (Sandbox Code Playgroud)
这是正确的做法,还是我应该注意哪些陷阱?例如,是否存在可能发生的静态初始化顺序问题,即在第一次调用getInst时,inst总是保证为NULL?
我一直在阅读有关线程安全的单例模式:
http://en.wikipedia.org/wiki/Singleton_pattern#C.2B.2B_.28using_pthreads.29
它在底部说,唯一安全的方法是使用pthread_once - 这在Windows上不可用.
这是保证线程安全初始化的唯一方法吗?
我在SO上读过这个帖子:
并且似乎暗示了原子操作系统级别的交换和比较功能,我在Windows上假设:
http://msdn.microsoft.com/en-us/library/ms683568.aspx
这可以做我想要的吗?
编辑:我想懒惰的初始化,因为只有一个类的实例.
另一个网站上有人提到在命名空间中使用全局(并且他将单例描述为反模式) - 它如何成为"反模式"?
一般承认的答案:
我已经接受了Josh的回答,因为我正在使用Visual Studio 2008 - 注意:对于未来的读者,如果您不使用此编译器(或2005) - 请勿使用接受的答案!
编辑: 除了return语句之外代码工作正常 - 我收到错误:错误C2440:'return':无法从'volatile Singleton*'转换为'Singleton*'.我应该将返回值修改为易失性Singleton*吗?
编辑:显然const_cast <>将删除volatile限定符.再次感谢Josh.
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html上的页面说,双重检查锁定在java中是有缺陷的.我只是想知道它是否也适用于其他语言(C#,Vb,C++等)
我读过双重检查锁定模式:是否破碎?,这是双重检查锁定?,如何解决Java中的"双重检查锁定"声明?说实话,我不知道共同的共识是什么.有人说是的,其他人说不.
无论如何,我的问题是它是否也适用于其他语言(C#,Vb,C++等)
我一直在寻找SO和MSDN的答案来回答这个问题,但似乎无法找到明确的最终答案......
我知道它是在C++ 11标准中并且当前的GCC版本就是这样的,但VC2010目前是否保证了本地静态变量初始化的线程安全性?
即:这对VC2010有线程安全吗?
static S& getInstance()
{
static S instance;
return instance;
}
Run Code Online (Sandbox Code Playgroud)
...如果没有,目前使用VC2010在C++中获得线程安全的单例实现的最佳实践是什么?
编辑:正如Chris Betti的回答所指出的,VC2010没有实现本地静态变量init的线程安全性.
我有一个类应该从main()全局声明,并从程序中的其他声明的类访问,我该怎么做?
class A{
int i;
int value(){ return i;}
};
class B{
global A a; //or extern??
int calc(){
return a.value()+10;
}
}
main(){
global A a;
B b;
cout<<b.calc();
}
Run Code Online (Sandbox Code Playgroud) 让我们假设我有以下架构:
Dodo 单身课程 libdodolibdodo和libponny; 主程序称为Dodo::instance()Ponny来自libponny创建的类.它有Dodo单身标题mainwindow.cpp
#include "shared/dodo/dodo.h"
// ...
Dodo::instance()->setNumber(91);
Run Code Online (Sandbox Code Playgroud)
然后,在此调用之后,Ponny创建类(ponny.cpp)
ponny.cpp
#include "shared/dodo/dodo.h"
// ...
bool is = (Dodo::instance()->number() == 91);
// Will `is` be true?
Run Code Online (Sandbox Code Playgroud)
那么,我可以这样做吗?
美好的一天,朋友们.
从新手回来关于Obj-C的愚蠢问题:)
我正在尝试在Obj-C中实现单例设计模式:
@interface SampleSingleton : NSObject {
@private
static SampleSingleton* instance;
}
+(SampleSingleton*) getInstance;
Run Code Online (Sandbox Code Playgroud)
编译器返回错误:"在'静态'之前的预期说明符 - 限定符列表".