c++ - 三重检查锁定?

标签 c++ c multicore double-checked-locking lazy-initialization

因此,与此同时,我们知道双重检查锁定在 C++ 中不起作用,至少不能以可移植的方式起作用。

我刚刚意识到我在用于地形光线追踪器的惰性四叉树中有一个脆弱的实现。因此,我试图找到一种仍然以安全的方式使用延迟初始化的方法,因为我不想将内存使用量增加四倍并对大部分已实现的算法进行重新排序。

这次遍历的灵感来自C++ and the Perils of Double-Checked Locking第12页的模式,但试图做得更便宜:

(pseudo code!)

struct Foo {
    bool childCreated[4];
    Mutex mutex[4];
    Foo child[4];

    void traverse (...) {
        ...
        if (!childCreated[c]) { 
            // get updated view
            #pragma flush childCreated[c]
            if (!childCreated[c]) { 
                ScopedLock sl (mutex[c]);
                if (!childCreated[c]) {
                    create (c);
                    #pragma flush childCreated[c]  
                    childCreated[c] = true;
                }
            }
        }
    }
}

假设#pragmalush也将充当硬序列点,不允许编译器和处理器在它们之间重新排序操作。

您发现哪些问题?

编辑:版本 2,尝试考虑 Vlads 的回答(引入第三次冲洗):

(pseudo code!)

struct Foo {
    bool childCreated[4];
    Mutex mutex[4];
    Foo child[4];

    void traverse (...) {
        ...
        if (!childCreated[c]) { 
            // get updated view
            #pragma flush childCreated[c]
            if (!childCreated[c]) { 
                ScopedLock sl (mutex[c]);
                #pragma flush childCreated[c]
                if (!childCreated[c]) {
                    create (c);
                    #pragma flush childCreated[c]
                    childCreated[c] = true;
                }
            }
        }
    }
}

编辑:版本 3,我不知何故发现这与版本 2 相当,因为我没有使用子级本身,而是使用原始标志来检查有效性,基本上依赖于创建之间的内存屏障一个 child 并向该标志写入内容。

(pseudo code!)

struct Foo {
    bool childCreated[4];
    Mutex mutex[4];
    Foo child[4];

    void traverse (...) {
        ...
        if (!childCreated[c]) { 
            ScopedLock sl (mutex[c]);
            #pragma flush childCreated[c]
            if (!childCreated[c]) {
                create (c);
                #pragma flush childCreated[c]
                childCreated[c] = true;
            }
        }
    }
}

最佳答案

看来你的模式不正确。考虑线程#1 执行到第一个#pragmalush 之后的情况。然后控制权切换到线程 #2,该线程继续创建一个 c,控制权在第二个 #pragmalush 之前被收回。现在第一个线程醒来,并重新创建子线程。

编辑:抱歉,错误:它将无法获取锁定。

编辑 2:不,仍然正确,因为该值不会在线程 #1 中刷新

关于c++ - 三重检查锁定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2372468/

相关文章:

c++ - Qt - 禁用 QDialog 的 "?"按钮

c++ - 使用 LLVM 链接器生成 C 代码

android - 如何在每个 CPU 上运行代码

java - stm实现问题

c++ - "ambiguous overload for ' operator[] '"如果存在到 int 的转换运算符

c++ - g++ : Compilation failed to deduce reference array in case of temporary object

c - 如何在 C 中检查十六进制数 (%x) 是否以某个数字开头?

c - 使用gnu-efi读取文件

c - Sendto() 仍然返回我发送的 0 个字节

c++ - 在多线程中使用 libev