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

时间:2018-06-29 08:21:02

标签: c++ multithreading memory-model

我是否需要在“ p = tmp”之前插入篱笆以避免内存重新排序?由于从线程2的角度对内存进行了重新排序,而不使用fence / atomic / mutex,是否有可能在“(* tmp)[1] = 2”之前执行“ p = tmp”?

线程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);

2 个答案:

答案 0 :(得分:2)

  

由于内存的原因,是否有可能在“(* tmp)[1] = 2”之前执行“ p = tmp”   从线程2的角度重新排序,而无需使用fence / atomic / mutex?

会发生吗

应该将volatile添加到阻止重新排序的内容列表中,但是volatile仍然不能避免数据争夺

  

我是否需要在“ 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);

答案 1 :(得分:1)

您有线程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之前,应先检查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
相关问题