我的应用程序配置存储在单例类中,如下所示(简化):
class Conf
{
Conf();
Conf(const Conf&);
Conf& operator=(const Conf&);
~Conf();
public:
static Conf& instance()
{
static Conf singleton;
return singleton;
};
static void setProperty(const std::string& name,
const std::string& value);
static std::string getProperty(const std::string& name);
private:
QMutex _mutex;
std::map<std::string, std::string> _properties;
};
因为可以从许多线程访问配置类,所以我使用互斥来进行同步:
void Conf::setProperty(const std::string& name,
const std::string& value)
{
QMutexLocker(&Conf::instance()._mutex);
Conf::instance()._properties[name]=value;
}
std::string Conf::getProperty(const std::string& name)
{
QMutexLocker(&Conf::instance()._mutex);
return Conf::instance()._properties[name];
}
Conf::instance()
方法是否也需要锁定?
我发现了类似的问题:does a getter function need a mutex?, 但在我的情况下,没有setter方法(假设在线程开始之前创建了单例的实例)。
答案 0 :(得分:5)
如果您正在使用c ++ 11或更高版本,则保证静态单例的创建是线程安全的。
如果您仍在使用c ++ 03,那么您需要提供自己的机制。
按要求:
c ++ 11标准第6.7节:
这样的变量在控件第一次通过其声明时被初始化;这样的变量在初始化完成后被认为是初始化的。 [...]如果控件在初始化变量时同时进入声明,则并发执行应等待初始化完成。
脚注:
实现不得在执行初始化程序时引入任何死锁。
答案 1 :(得分:3)
在C ++ 11 instance()
中不需要互斥锁,在C ++ 98中,它可以作为两个线程同时输入一个开始构造对象。 C ++ 11确保static
&#39; local&#39;变量
答案 2 :(得分:2)
以这种方式使用no,instance()不需要互斥锁。
但是我会通过在私有部分中移动实例来强制执行此操作,从而允许客户端代码仅使用setProperty / getProperty。