簡體   English   中英

在C ++ 11之前在C ++中實現Double Check Lock Pattern是否安全

[英]Is it safe to implement Double Check Lock Pattern in C++ before C++11

class SelfTesting
{
private:
    char * pChar;
    SelfTesting()
    {
        pChar = new char[1024 * 1024 * 1024];
    }
public:
    static SelfTesting * pSelf;

    static SelfTesting& GetInst()
    {
        if (!pSelf)
        {
            boost::lock_guard<boost::mutex> lock(g_boost_mutex);
            if (!pSelf)
            {
                pSelf = new SelfTesting;
            }
        }
        return *pSelf;
    }
};

一般來說,我知道問題是由以下原因引起的:

1. allocate memory for `SelfTesting`
2. store the pointer to the allocated memory in `pChar`
3. initialize `SelfTesting`
  1. 如果其他線程在步驟2和3之間觸摸指針,則發生數據爭用情況。
  2. 如果指針復制不是原子的,則也可能發生數據爭用情況。

我知道我可以使用本地靜態變量在C ++ 11中實現這種模式。 我的問題是上面的實現線程是安全的,或者當我在C ++ 11之前使用C ++標准時它是未定義的。 boost::mutex是否確保lock死后pSelf會更新?

如上所述,這種模式在任何版本的C ++中都不安全。 在C ++ 11個條款,你有外讀取之間的數據爭pSelf和寫pSelf

一般來說,在C ++ 11之前,沒有保證多線程代碼的安全性。 關於C ++ 11最重要的一點是它在C ++執行的抽象模型中引入了可能首先存在多個執行線程的想法。 在此之前,絕對沒有任何關於多線程執行的保證,因為這個概念不存在。 就標准而言,任何具有多個線程的情況都是未定義的,因為它沒有定義線程是什么。

這基本上意味着您在C ++ 98中編寫的任何多線程代碼完全取決於您使用的特定實現。 主流編譯器有一些你可以依賴的東西,盡管在C ++ 11的開發中,在有多個線程的情況下,在各種編譯器中發現了幾個實際上並不安全的行為(特別是優化)。

但這都是無關緊要的,因為你所編寫的代碼從未保證在我所知道的任何編譯器中都是安全的。 使用Visual C ++,您可以通過使pSelf volatile (VC ++處理的volatile變量類似於atomics)使其安全,但這在GCC中不起作用。 在GCC中,您必須使用原子內在函數或Boost.Atomic庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM