什么是三重检查锁定模式

时间:2010-09-02 13:32:47

标签: c++ multithreading

参考: - 由Andrei Alexandrescu撰写的“现代C ++设计:应用的通用编程和设计模式” 第6章实施单身人士。

即使你放了挥发性物质,也不能保证双重检查锁定模式安全和便携。为什么会这样?

如果有人可以提供任何解释什么是宽松记忆模型的好链接以及双重检查模式的确切问题。{或者有人可以解释}

我曾经认为volatile已经解决了这个问题但在我读完这本书之前似乎不正确。

3 个答案:

答案 0 :(得分:8)

  

即使你放了挥发性物质,也不能保证双重检查锁定模式安全和便携。为什么会这样?

我会尝试提供一些背景信息。

C ++中volatile有三个(Boehm & McLaren)便携式用例,其中没有一个与多线程有关。 Alexandrescu确实提出a hack很长一段时间回到cajole C ++的类型系统来帮助进行多线程编程,但就是这样。关于comp.programming.threads,请参阅David Butenhof的reply

关于此限定符的混淆源于这样一个事实,即某些编译器(例如英特尔)volatile带来了内存栅栏语义 - 这是安全多线程所需要的。但这是 便携式,不应该依赖。

此外,大多数专业级编译器未能完美地实现volatile。见Regehr et al.

混淆可能与Java(另一种语言)完全不同semantics for volatile并且确实涉及内存栅栏这一事实有很大关系。但请注意,即使是双重检查锁定is not free from issues

答案 1 :(得分:1)

大多数时候使用一个你总是检查的简单锁对于单身人士来说足够快。如果你经常访问变量或字段,你总是可以将单例缓存。

在你证明一个简单的锁不够快之前,不要考虑“黑客”以避免锁定。编写无bug的便携式线程代码很难,而不会给自己带来更多问题。

答案 2 :(得分:1)

我不明确知道“三重检查锁定”是什么,但是近十年前编译器编写者和硬件工程师开始从程序员手中接过控制权时,我的懒惰init有3种状态:      枚举eINITIALIZATION_STATE {FIRST_INITIALIZER = 0,INITIALIZING,INITIALIZED};

(想象一下,如果您发送的库软件与现场重要的多线程算法完全不兼容!但我已经为SMP机器编写了30多年的代码和多核“革命”(HA!)在过去的十年里真的开始滚动。编译器编写者和硬件工程师要么不知道他们在破坏什么,要么他们认为没关系......但是足够的编辑!)

...的sooo

enum eINITIALIZATION_STATE {FIRST_INITIALIZER=0,INITIALIZING,INITIALIZED} ;

然后你有一个初始化控制变量:

static int init_state;  //its 0 initialized 'cause static

那么成语是:

    IF(init_state == INITIALIZED)
        return your pointer or what ever;//the "normal" post initialization path
    ENDIF
    IF(init_state == FIRST_INITIALIZER)
        IF(compare_and_swap(&init_state,
                            INITIALIZING,
                            FIRST_INITIALIZER)==FIRST_INITIALIZER)

           //first initializer race resolved - I'm first.

           do your initialization here;

           //And now resolve the race induced by the compiler writers and the HW guys
           COMPILER_FENCE();//needs macro for portability
           HARDWARE_FENCE();//needs macro for portability

           //on intel using cas here supplies the HARDWARE_FENCE();
           compare_and_swap(&init_state,INITIALIZER,INITIALIZING);
           //now you can return your pointer or what ever or just fall through
       ENDIF
    ENDIF
    DOWHILE(*const_cast<volatile const int*>(&init_state)!=INITIALIZED)
        relinquish or spin;
    ENDDO
    return your pointer or what ever;

我不确定这是否意味着什么,但由于3个州,我怀疑这可能与“三重检查锁定”的含义相同(或至少相似)。