简体   繁体   中英

Is this C++ pointer usage thread safe?

Do I need insert fence before "p = tmp" to avoid memory reordering? Is it possible "p=tmp" executed before "(*tmp)[1]=2" due to memory reordering from the view of thread 2 without using fence/atomic/mutex?

thread 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;

thread 2

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

Is it possible "p=tmp" executed before "(*tmp)[1]=2" due to memory reordering from the view of thread 2 without using fence/atomic/mutex?

can it happen yes

volatile should be added to the list of things preventing the reordering but volatile would still not protect from the data race

Do I need insert fence before "p = tmp" to avoid memory reordering?

you need to add a synchronization but fences are often suboptimal and were they are needed is architecture specific. atomic would be better suited in that case

with #include <atomic>

thread 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;

thread 2

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

You have thread 2 to wait for thread 1 to complete its chunk of work

thread 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

thread 2

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

or you can guard p with CS or mutex in both threads but then p should be checked for validity before usage in thread 2

thread 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

thread 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM