Безопасен ли этот поток использования указателя C ++? - PullRequest
0 голосов
/ 29 июня 2018

Нужно ли вставлять ограждение перед "p = tmp", чтобы избежать переупорядочения памяти? Возможно ли выполнение "p = tmp" перед "(* tmp) [1] = 2" из-за переупорядочения памяти с точки зрения потока 2 без использования fence / atomic / mutex?

нить 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 голосов
/ 29 июня 2018

Возможно ли выполнить "p = tmp" раньше "(* tmp) [1] = 2" из-за памяти переупорядочение с точки зрения потока 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);
0 голосов
/ 29 июня 2018

У вас есть поток 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);

или вы можете защитить p с помощью CS или мьютекса в обоих потоках, но затем p следует проверить на достоверность перед использованием в потоке 2

нить 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...