下面的代码显示了通过原子标志获取共享状态的两种方法。读取器线程调用poll1()
或poll2()
检查写入器是否已发出标志。
投票选项#1:
bool poll1() {
return (flag.load(std::memory_order_acquire) == 1);
}
投票选项#2:
bool poll2() {
int snapshot = flag.load(std::memory_order_relaxed);
if (snapshot == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
return true;
}
return false;
}
请注意,选项 #1在较早的问题中提出,选项 #2 类似于cppreference.com 上的示例代码。
假设读者同意仅在poll
函数返回时检查共享状态true
,这两个poll
函数是否正确且等价?
选项#2 有标准名称吗?
每个选项的优点和缺点是什么?
选项#2 在实践中可能更有效吗?是否有可能降低效率?
这是一个完整的工作示例:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
int x; // regular variable, could be a complex data structure
std::atomic<int> flag { 0 };
void writer_thread() {
x = 42;
// release value x to reader thread
flag.store(1, std::memory_order_release);
}
bool poll1() {
return (flag.load(std::memory_order_acquire) == 1);
}
bool poll2() {
int snapshot = flag.load(std::memory_order_relaxed);
if (snapshot == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
return true;
}
return false;
}
int main() {
x = 0;
std::thread t(writer_thread);
// "reader thread" ...
// sleep-wait is just for the test.
// production code calls poll() at specific points
while (!poll2()) // poll1() or poll2() here
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::cout << x << std::endl;
t.join();
}