class Singleton
{
public:
static Singleton & Instance()
{
// Since it's a static variable, if the class has already been created,
// It won't be created again.
// And it **is** thread-safe in C++11.
static Singleton myInstance;
// Return a reference to our instance.
return myInstance;
}
// delete copy and move constructors and assign operators
Singleton(Singleton const&) = delete; // Copy construct
Singleton(Singleton&&) = delete; // Move construct
Singleton& operator=(Singleton const&) = delete; // Copy assign
Singleton& operator=(Singleton &&) = delete; // Move assign
// Any other public methods
protected:
Singleton()
{
// Constructor code goes here.
}
~Singleton()
{
// Destructor code goes here.
}
// And any other protected methods.
}
2 回答
C 98/03完全不支持线程 . 如果您正在使用C 98或03编译器,那么您几乎不会使用Boost,或某些(或多或少)特定于操作系统的东西,例如pthreads或Win32的线程原语 .
C 11有一个相当完整的线程支持库,有互斥锁,锁,线程本地存储等 .
然而,我觉得有必要指出,备份并做更多考虑是否需要/想要一个Singleton可能会更好 . 说实话,单身模式在很大程度上已经失宠了 .
编辑:重读这个,我有点想跳过一件事:至少当我使用它们时,任何/所有单例都在任何辅助线程启动之前完全初始化 . 这引起了对初始化中线程安全性的关注,这完全没有实际意义 . 我想在你启动辅助线程之前你可能有一个你无法初始化的单例,所以你需要处理这个问题,但至少对它来说这是一个非常不寻常的例外,我只会在/如果绝对必要 .
对我来说,使用c 11实现单例的最佳方法是:
这是一个c 11功能,但通过这种方式,您可以创建一个线程安全的Singleton . 根据新标准,不再需要关心这个问题 . 对象初始化只能由一个线程完成,其他线程将等待它完成 . 或者你可以使用std :: call_once .
如果要对单例资源进行独占访问,则必须对这些函数使用锁定 .
不同类型的锁:
使用 atomic_flg_lck:
使用 atomic:
使用 mutex:
仅适用于 Windows :
atomic 和 and atomic_flg_lck 使线程保持旋转计数 . Mutex 只是睡觉了 . 如果等待时间太长也许最好睡眠线程 . 最后一个“ CRITICAL_SECTION ”使线程保持旋转计数直到消耗时间,然后线程进入休眠状态 .
如何使用这些关键部分?
使用raii成语 . 用于锁定关键部分的构造函数和用于解锁它的析构函数 .
例
此实现是线程安全且异常安全的,因为变量锁保存在堆栈中,因此当函数作用域结束(函数结束或异常)时,将调用析构函数 .
我希望你觉得这很有帮助 .
谢谢!!