2015-05-21 102 views
3

我具有存儲在一個單獨的類我的應用程序的結構,這樣的(簡化):多線程單例:實例方法是否需要互斥鎖?

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方法(讓我們假設在線程啓動之前創建單例實例)。

在C++ 11 instance()

回答

5

如果您使用的是C++ 11或更高版本,則保證靜態單例的創建是線程安全的。

如果您仍在使用C++ 03,那麼您需要提供自己的機制。

由請求:

部分中的C++ 11標準的6.7:在第一時間控制穿過它的聲明

這樣的變量被初始化;這種變量在其初始化完成時被認爲是初始化的。 [...]如果控制在變量初始化時同時輸入聲明,則併發執行應等待初始化完成。

註腳:

實行不得介紹周圍的初始化的執行任何僵局。

+0

您可以給出您對C++ 11的自動線程安全聲明的引用。 – doron

+0

@doron如此補充。 –

+0

很酷。你每天學習新的東西。 – doron

3

不需要互斥,在C++ 98它作爲兩個線程可能在一旦開始構建對象輸入。 C++ 11確保static「本地」變量的單一初始化。

+0

如果我假定在線程啓動之前創建了單例的實例,那麼不需要鎖定? – user2449761

+0

@ user2449761第一次控制流過其定義時創建的單例。即第一次調用Conf :: instance()' –

2

這樣使用沒有,()的實例並不需要一個互斥。

但是我會通過移動私有部分中的實例來執行此操作,以允許客戶端代碼只使用setProperty/getProperty。

+0

不錯的主意,謝謝 – user2449761

相關問題