#include <iostream>
#include <atomic>
#include <thread>
#include <cassert>
struct Node{
int value;
std::atomic<Node*> next;
};
int main(){
std::atomic<Node*> ptr = (Node*)0;
auto t1 = std::thread([&ptr](){
auto r = new Node{1,std::atomic<Node*>{(Node*)nullptr}}; // #1
ptr.store(r,std::memory_order::relaxed);
});
auto t2 = std::thread([&ptr](){
Node* r = nullptr;
while(r==nullptr){
r = ptr.load(std::memory_order::relaxed);
}
assert(r->value == 1); // #2
assert(r->next.load(std::memory_order::relaxed) == nullptr); // #3
});
t1.join();
t2.join();
}
#2
和#3
是否能保证读取#1
中写入的值?如果不是,请问原因是什么?
应该没问题,因为
ptr
只被分配一次,所以 r
在循环之后将始终具有 ptr
的非空值。像你一样读取 ptr->value 也很好。缺少一件事。 delete ptr;
退出前main()
。
由于您使用的是
std::atomic<>
并且仅轻松加载/存储,因此您应该避免如此冗长,这将使您的代码更具可读性。考虑一下:
int main() {
std::atomic<Node*> ptr = nullptr;
auto t1 = std::thread([&ptr]() {
ptr = new Node{1, nullptr}; // #1
});
auto t2 = std::thread([&ptr]() {
Node* r = nullptr;
while ((r = ptr) == nullptr) {
}
assert(r->value == 1); // #2
assert(r->next == nullptr); // #3
});
t1.join();
t2.join();
delete ptr;
return 0;
}