这C++指针使用线程安全吗?

Is this C++ pointer usage thread safe?

本文关键字:安全 线程 C++ 指针      更新时间:2023-10-16

我需要在"p = tmp"之前插入围栏以避免内存重新排序吗?是否可以在"(*tmp([1]=2"之前执行"p=tmp",因为从线程 2 的视图重新排序而不使用栅栏/原子/互斥锁?

线程 1

extern const std::map<int, int>* p;
auto tmp = new std::map<int, int>;
(*tmp)[1] = 2;
...
(*tmp)[2] = 3;
// do I need insert fence here to make sure above operation on tmp ready before tmp assigned to p?
p = tmp;

线程 2

extern const std::map<int, int>* p; // suppose p initalized with {{1:2}}
assert(p->find(1)->second == 2);

由于内存的原因,是否有可能在"(*tmp([1]=2"之前执行"p=tmp" 从线程 2 的视图重新排序而不使用栅栏/原子/互斥锁?

它会发生吗 是的

易失性应该添加到阻止重新排序的事物列表中,但易失性仍然不能防止数据争用

我是否需要在"p = tmp"之前插入围栏以避免内存重新排序?

您需要添加同步,但围栏通常是次优的,并且需要它们是特定于体系结构的。 在这种情况下,原子会更适合

#include <atomic>

线程 1

extern std::atomic<const std::map<int, int>*> p;
auto tmp = new std::map<int, int>;
(*tmp)[1] = 2;
...
(*tmp)[2] = 3;
// do I need insert fence here to make sure above operation on tmp ready before tmp assigned to p?
p = tmp;

线程 2

extern std::atomic<const std::map<int, int>*> p; // suppose p initalized with {{1:2}}
assert(p->find(1)->second == 2);

你有线程 2 等待线程 1 完成其工作块

线程 1

extern const std::map<int, int>* p;
auto tmp = new std::map<int, int>;
(*tmp)[1] = 2;
...
(*tmp)[2] = 3;
p = tmp;
// set event here

线程 2

extern const std::map<int, int>* p; // suppose p initalized with {{1:2}}
// wait for event here
assert(p->find(1)->second == 2);

或者您可以在两个线程中使用 CS 或互斥锁保护p,但在线程 2 中使用之前应检查 p 的有效性

线程 1

extern const std::map<int, int>* p;
auto tmp = new std::map<int, int>;
// lock mutex here
(*tmp)[1] = 2;
...
(*tmp)[2] = 3;
p = tmp;
// unlock mutex here

线程 2

extern const std::map<int, int>* p; // suppose p initalized with {{1:2}}
// lock mutex here
// check if p is initialized:
// if (p is ok){
assert(p->find(1)->second == 2);
// }
// unlock mutex here