Clang ThreadSanitizer: разблокировка разблокированного мьютекса, и атомная система создает гонку данных

Я анализирую потоки с помощью ThreadSanitizer и получаю предупреждение, которое очень, очень запутывает мое понимание того, как работают мьютексы. Я использую gcc 6.3 на Debian Stretch.

В одном классе у меня есть:

auto MyPtr = std::make_shared<MyClass>(...);

В другом месте, которое называется другим потоком, у меня есть:

if(MyPtr.get()) {...}

ThreadSanitizer предупредил меня о состоянии гонки, и это здорово. Поэтому я исправил это следующим образом:

std::unique_lock<decltype(MyMutex)> lg(MyMutex); //MyMutex is std::mutex
auto MyPtr = std::make_shared<...>(...);
lg.unlock();

И другое место:

std::unique_lock<decltype(MyMutex)> lg(MyMutex);
if(MyPtr.get()) {...}
// mutex unlocks at the end of the function, which is like after another if-condition.

Теперь гонка данных ушла, и ThreadSanitizer сообщает, что Mutex разблокируется «дважды» …

WARNING: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread)

и это указывает на unlock() вызов + конец другой функции.

Как мьютекс может быть разблокирован дважды? Может кто-нибудь объяснить?

Теперь, так как это вызвало у меня головную боль, я решил сделать это вместо:

std::shared_ptr<MyClass> MyPtr; //in the class definition
std::atomic_store(&MyPtr, std::make_shared<MyClass>(...));

И теперь я получаю жалобу на передачу данных:

WARNING: ThreadSanitizer: data race

Так я неправильно использую ThreadSanitizer? Может кто-нибудь объяснить, что здесь происходит?

0

Решение

Я никогда не понимал проблему мьютекса, но я смог избавиться от гонки данных с атомарностью, сделав другую загрузку атомарной:

if(std::atomic_load(&MyPtr).get()) {...}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]