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 回答