多线程单例:实例方法是否需要互斥锁?

时间:2015-05-21 13:50:11

标签: c++ multithreading singleton mutex

我的应用程序配置存储在单例类中,如下所示(简化):

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方法(假设在线程开始之前创建了单例的实例)。

3 个答案:

答案 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。