UPD :似乎我在下面解释的问题不存在。我不能在一周内重现它,我开始怀疑它是由编译器中的一些错误或内存损坏引起的,因为它不再复制了。
我试图在C ++中实现我自己的递归互斥,但由于某种原因,它失败了。我试着调试它,但我卡住了。 (我知道std中有递归互斥,但是我需要在STL不可用的项目中使用自定义实现;这个实现只是一个想法的检查)。我还没有想过效率,但我不明白为什么我的直接实施不起作用。
首先,这里是RecursiveMutex的实现:
class RecursiveMutex
{
std::mutex critical_section;
std::condition_variable cv;
std::thread::id id;
int recursive_calls = 0;
public:
void lock() {
auto thread = std::this_thread::get_id();
std::unique_lock<std::mutex> lock(critical_section);
cv.wait( lock, [this, thread]() {
return id == thread || recursive_calls == 0;
});
++recursive_calls;
id = thread;
}
void unlock() {
std::unique_lock<std::mutex> lock( critical_section );
--recursive_calls;
if( recursive_calls == 0 ) {
lock.unlock();
cv.notify_all();
}
}
};
失败的测试很简单,它只运行两个线程,它们都锁定并解锁相同的互斥锁(这里没有测试互斥锁的递归性质)。这是:
std::vector<std::thread> threads;
void initThreads( int num_of_threads, std::function<void()> func )
{
threads.resize( num_of_threads );
for( auto& thread : threads )
{
thread = std::thread( func );
}
}
void waitThreads()
{
for( auto& thread : threads )
{
thread.join();
}
}
void test () {
RecursiveMutex mutex;
while (true) {
int count = 0;
initThreads(2, [&mutex] () {
for( int i = 0; i < 100000; ++i ) {
try {
mutex.lock();
++count;
mutex.unlock();
}
catch (...) {
// Extremely rarely.
// Exception is "Operation not permited"
assert(false);
}
}
});
waitThreads();
// Happens often
assert(count == 200000);
}
}
在这段代码中,我有两种错误:
我很少在RecursiveMutex::lock()
中收到包含消息&#34;不允许操作的异常&#34;并从cv.wait
抛出。据我所知,当在不属于该线程的互斥锁上调用wait
时,抛出此异常。与此同时,我将其锁定在调用wait
之上,因此情况并非如此。
在大多数情况下,我只是在控制台中收到一条消息&#34;在没有活动异常的情况下终止呼叫&#34;。
我的主要问题是错误是什么,但我也很高兴知道如何在这样的代码中调试和激发竞争条件。
P.S。我使用Desktop Qt 5.4.2 MinGW 32位。