我已经实现了迈耶的单例模式。我尝试在多线程环境中做一些测试它的东西。以下是我在C++中实现该类的方式。
#include<thread>
#include<mutex>
class singleton {
public:
static singleton& instance() {
std::lock_guard<std::mutex> lck(mtx);
static singleton *my = new singleton;
return *my;
}
private:
static std::mutex mtx;
singleton() {}
~singleton() {}
singleton(const singleton &) {}
singleton& operator=(const singleton &) {}
};
但是当我用g++ -std=c++11 singleton.cpp -o singleton -lpthread
编译它时,它说
/tmp/ccfEBnmN.o: In function `singleton::instance()':
singleton.cpp(.text._ZN11singleton12instanceEv[_ZN11singelton12instanceEv]+0x10):
undefined reference to `singleton::mtx' collect2: error: ld returned 1 exit status
我知道这可能是设计中的一些问题,因为如果不初始化第一个单例实例,我们如何获得 mtx。如果在这种情况下,我的问题是如何基于我的代码实现线程安全的单例类?我们如何在我的单例类中初始化 mtx?
我知道有一种传统的方法可以通过维护指向单例类的静态指针来创建单例模式。但实际上,这不是"如此"线程安全的。甚至在 instance(( 方法中应用双重检查机制。
你在 singleton
中声明了 mtx
,但未能定义它,它必须在 singleton
之外,如下所示:
std::mutex singleton::mtx;
这应该在源文件中,而不是标头中(否则,当您/如果将标头包含在多个源文件中时,您将收到多个定义错误(。
第二点:你展示的根本不是迈耶的单例模式。对于 Meyer 的单例,您可以在函数中定义单例的静态实例:
static singleton &instance() {
static singleton my;
return my;
}
使用这个,你根本不清楚你是否真的需要一个互斥锁。
数据成员mtx
需要一个定义。将其放在源文件中:
std::mutex singleton::mtx;
更准确地说,std::lock_guard<std::mutex> lck(mtx)
odr 使用mtx
因此需要定义它。当链接器无法解析引用时,会出现链接时错误。
另请注意,在 C++11 中,具有静态存储持续时间的对象初始化是线程安全的,您不需要互斥锁。