std::atomic 内存屏障可以用于在线程之间传输非原子数据吗?
Can std::atomic memory barriers be used to transfer non-atomic data between threads?
是否符合以下代码标准? (或者它是否可以在不使 x
成为原子或 volatile
的情况下变得合规?)
这类似于 an earlier question,但是我想引用 C++ 标准的相关部分。
我担心原子 store()
和 load()
没有为非原子变量(下例中的 x
)提供足够的编译器屏障来正确释放和获取语义。
我的目标是实现无锁基元,例如队列,它可以在线程之间传输指向常规 C++ 数据结构的指针。
#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 poll() {
return (flag.load(std::memory_order_acquire) == 1);
}
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 (!poll())
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::cout << x << std::endl;
t.join();
}
有了acquire/release,是的,这就够了。相关引述(来自cppreference——在大多数情况下达到标准):
Memory Model
When an evaluation of an expression writes to a memory location and another evaluation reads or modifies the same memory location, the expressions are said to conflict. A program that has two conflicting evaluations has a data race unless either
both conflicting evaluations are atomic operations (see std::atomic
)
- one of the conflicting evaluations happens-before another (see
std::memory_order
)
std::memory_order
Release-Acquire ordering
If an atomic store in thread A is tagged memory_order_release
and an atomic load in thread B from the same variable is tagged memory_order_acquire
, all memory writes (non-atomic and relaxed atomic) that happened-before the atomic store from the point of view of thread A, become visible side-effects in thread B, that is, once the atomic load is completed, thread B is guaranteed to see everything thread A wrote to memory.
是否符合以下代码标准? (或者它是否可以在不使 x
成为原子或 volatile
的情况下变得合规?)
这类似于 an earlier question,但是我想引用 C++ 标准的相关部分。
我担心原子 store()
和 load()
没有为非原子变量(下例中的 x
)提供足够的编译器屏障来正确释放和获取语义。
我的目标是实现无锁基元,例如队列,它可以在线程之间传输指向常规 C++ 数据结构的指针。
#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 poll() {
return (flag.load(std::memory_order_acquire) == 1);
}
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 (!poll())
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::cout << x << std::endl;
t.join();
}
有了acquire/release,是的,这就够了。相关引述(来自cppreference——在大多数情况下达到标准):
Memory Model
When an evaluation of an expression writes to a memory location and another evaluation reads or modifies the same memory location, the expressions are said to conflict. A program that has two conflicting evaluations has a data race unless either
both conflicting evaluations are atomic operations (seestd::atomic
)- one of the conflicting evaluations happens-before another (see
std::memory_order
)std::memory_order
Release-Acquire ordering
If an atomic store in thread A is tagged
memory_order_release
and an atomic load in thread B from the same variable is taggedmemory_order_acquire
, all memory writes (non-atomic and relaxed atomic) that happened-before the atomic store from the point of view of thread A, become visible side-effects in thread B, that is, once the atomic load is completed, thread B is guaranteed to see everything thread A wrote to memory.