3
我得到我的C++程序,它使用的std ::线程的std ::互斥的std :: condition_variable死锁等死锁没有用户代码
没有什么本身奇怪的这件事,直到我看看堆栈每个在我进程中的线程的:
8532 0 Main Thread Main Thread msvcr120.dll!Concurrency::details::ExternalContextBase::Block Normal
[email protected]()
[email protected]()
[email protected]()
msvcr120.dll!Concurrency::details::ExternalContextBase::Block() Line 145
[email protected]()
[email protected]()
[email protected]()
msvcr120.dll!_initterm(void (void) * * pfbegin, void (void) * * pfend) Line 954
-
6484 0 Worker Thread [email protected]() [email protected] Normal
[email protected]()
[email protected]()
[email protected]@12()
[email protected]()
[email protected]()
-
6296 0 Worker Thread msvcr120.dll!_threadstartex msvcr120.dll!Concurrency::details::ExternalContextBase::Block Normal
[email protected]()
[email protected]()
[email protected]()
msvcr120.dll!Concurrency::details::ExternalContextBase::Block() Line 145
msvcp120.dll!std::_Thrd_startX(struct _Thrd_imp_t *,unsigned int (*)(void *),void *)
msvcr120.dll!_callthreadstartex() Line 376
msvcr120.dll!_threadstartex(void * ptd) Line 354
[email protected]@12()
[email protected]()
[email protected]()
没有一个线程似乎在执行我的代码,并且我知道我们已经进入了main,因为程序在挂起之前做了一些事情。
我使用下面的类与我的std ::线程进行通信,如果我做了一些错误有:
template <typename T>
class BlockingQueue
{
public:
BlockingQueue() : _active(true) {}
bool Get(T& out)
{
std::unique_lock<std::mutex> lock(_mutex);
_cv.wait(lock, [&](){ return !_queue.empty() || !_active; });
if (_queue.empty())
{
assert(!_active);
return false;
}
out = std::move(_queue.front());
_queue.pop();
return true;
}
void Put(const T& in)
{
{
std::unique_lock<std::mutex> lock(_mutex);
_queue.push(in);
}
_cv.notify_one();
}
void Put(T&& in)
{
{
std::unique_lock<std::mutex> lock(_mutex);
_queue.push(std::move(in));
}
_cv.notify_one();
}
void Finish()
{
{
std::unique_lock<std::mutex> lock(_mutex);
_active = false;
}
_cv.notify_all();
}
private:
bool _active;
std::mutex _mutex;
std::condition_variable _cv;
std::queue<T> _queue;
};
我有两个想法,现在:
- 主要有出于某种原因已经退出。这是一个PoC,所以当出现错误时,我们登录到stdout并调用exit()(是的,我知道,不是最好的,这是从另一个用C++编写的C风格程序改编的)。我没有看到任何记录到终端的东西,但我想有可能输出被缓冲并且还没有写出来?
- 调试器以某种方式对我说谎。通常,当它执行此操作时,会将
[frames below may be missing/incorrect]
放入堆栈跟踪中,但也可能在没有这种情况下发生。
您应该通知互斥锁里面,或者你可能会遇到种族: 1.'_cv.wait()'计算谓词,它返回'FALSE' 2'notify_all'被称为 3.等待' (锁)'在'_cv.wait()中调用' 不知道这是不是问题 – StenSoft 2015-02-06 20:20:06
我在cppreference.com上查看std :: condition_variable的文档,它似乎说你没有在通知的时候不需要保持锁定,事实上这样做是一种性能悲观化(这是有道理的,因为任何由于通知而唤醒的线程会立即尝试抢占锁并失败) – Bwmat 2015-02-06 20:21:55
“通知线程不需要锁定与t所持有的锁相同的互斥锁他在等待线程;实际上这样做是悲观化的,因为通知的线程会立即再次阻塞,等待通知线程释放锁定。但是,某些实现(特别是pthread的许多实现)可以识别这种情况,并通过将等待线程从条件变量的队列直接传递到notify通知中的互斥队列而避免这种“快速等待”情形,而不会唤醒它向上。 “是他们说的。 – Bwmat 2015-02-06 20:23:16