我对使用内存屏障/围栏进行编程相当陌生,我想知道我们如何保证设置写入在随后在其他 CPU 上运行的工作函数中可见。例如,考虑以下情况:
int setup, sheep;
void SetupSheep(): // Run once
CPU 1: setup = 0;
... much later
CPU 1: sheep = 9;
CPU 1: std::atomic_thread_fence(std::memory_order_release);
CPU 1: setup = 1;
之后(不是同时)运行很多次:
void ManipulateSheep():
CPU 2: int mySetup = setup;
CPU 2: std::atomic_thread_fence(std::memory_order_acquire);
CPU 2: // Use sheep...
在 CPU 2 上,如果mySetup
为 1,sheep
则保证为 9——但我们如何保证它mySetup
不是 0?
到目前为止,我能想到的只是在 CPU 2 上旋转等待直到setup
1。但这似乎很丑陋,因为旋转等待只需要等待第一次ManipulateSheep()
被调用。肯定有更好的方法吗?
请注意,未初始化代码还有一个对称问题:假设您正在编写一个无锁数据结构,该结构在其生命周期内分配内存。在析构函数中(假设所有线程都已完成调用方法),您想要释放所有内存,这意味着您需要运行析构函数的 CPU 具有最新的变量值。在这种情况下甚至不可能旋转等待,因为析构函数无法知道“最新”状态是什么来检查它。
编辑:我想我要问的是:有没有办法说“等待我的所有商店传播到其他 CPU”(用于初始化)和“等待所有商店传播到我的 CPU”(用于未初始化)?