2

我正在使用 ThreadSanitizer 进行线程分析,我收到一个警告,这对我对互斥锁如何工作的理解非常非常困惑。我在 Debian Stretch 上使用 gcc 6.3。

在课堂上,在一个线程中,我有:

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 说互斥锁被“两次”解锁......

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 错了吗?有人可以解释这里发生了什么吗?

4

1 回答 1

1

我从来没有弄清楚互斥锁问题,但我能够通过使另一个负载原子化来摆脱与原子性的数据竞争:

if(std::atomic_load(&MyPtr).get()) {...}
于 2017-07-20T17:23:02.913 回答