1

「Scott Meyers によるダブル チェック ロックの危険性」に関する論文を読んでいました。http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf

著者は、ダブル チェック ロックが失敗する理由を示しています (ページ 3、セクション 4)。C++11 を使わずにこの問題を回避する方法を考えていました。C++ 11 を使用したくないというわけではありませんが、std::call_once などの関数を使用せずに解決できるかどうかを確認するだけです。

class Singleton {
public:
    static Singleton* instance();

private:
    static Singleton* pInstance;
    int someData_;
};


Singleton* Singleton::instance() 
{
    class SeqAssign{
    public:
        SeqAssign(Singleton*& pInst, Singleton* pNew):
        pInstance(pInst), pNewedInst(pNew){
        }
        ~SeqAssign(){
            pInstance = pNewedInst;
        }

    private:
        Singleton*& pInstance;
        Singleton*  pNewedInst;
    };

    if (pInstance == 0) { // 1st test
        Lock lock;
        if (pInstance == 0) { // 2nd test
            SeqAssign seq(pInstance, new Singleton);
        }
    }
    return pInstance;
}

Singleton::instance() のコードはマルチスレッド環境で動作しますか? SeqAssign クラスのコンストラクターとデストラクタが呼び出される順序は決定論的です。

4

1 に答える 1

2

いいえ。変数pInstanceは複数のスレッドからアクセスされます。修正済みです。コードには未定義の動作があります。そしてSeqAssign、追加のスレッド間シーケンスを導入しないため、あなたが何をするのかわかりません。

標準 C++ でダブル チェック ロギングを機能させる方法はありません。すべてのソリューションには、アトミック変数 (インライン アセンブラーを使用して実装される可能性があります) またはスレッド ローカル ストレージが含まれます。

于 2012-09-10T09:20:30.540 に答える