所以我有这个代码,这个代码运行良好,但在我看来,我锁定了两次,而且在我看来,如果第一个锁在第二个锁之前再次锁定,我有时会犯错误,在这种情况下,有人可以帮助我更好地理解独特锁的使用吗?什么是在PrepDequeue函数中完全执行的唯一锁定和作用域锁定?
m_mtx = mutable boost :: mutex
m_event = boost :: condition_variable
并且enqueu和dequeue是一些任意队列......
插入功能:
/** : */
void TaskImp::CmdsQueue::Enqueue(Command* cmd)
{
boost::mutex::scoped_lock guard(m_mtx);
bool signal = m_enqueue.empty();
m_enqueue.push_back(cmd);
if (signal) {
m_event.notify_one();
}
}
交换功能(所以出列和排队总是在不同的队列上工作):
/** : */
void TaskImp::CmdsQueue::PrepDequeue(bool wait, size_t ms)
{
if (wait) {
//QueueingMutex_t dummy; once upon a time there was a dummy here
Timeout timeout(ms);
boost::unique_lock<boost::mutex> lock(m_mtx); // <=== what is it waiting for?
if (!m_event.timed_wait(lock, timeout, [this] () {
return !this ->m_enqueue.empty();
})) {
return;
}
}
boost::mutex::scoped_lock guard(m_mtx); // safe lock? duplicated?
m_enqueue.swap(m_dequeue);
}
答案 0 :(得分:0)
拳头我会试着回答你的问题:
PrepDequeue
正在为要排队的元素做好准备,当队列为空时似乎wait == true
。
由于上一次锁定超出范围,锁定是安全的。
现在我的想法:
设计不安全,使用队列就好像它们没有意义一样,只使用一个同步对象同步它们也没有意义。
更糟糕的是,可能有一个线程而不是运行PrepDequeue
的线程,并且该线程可能在调用Dequeue
时出现问题,但由于您使用相同的同步对象两个队列,你最终可能会从一个空的队列中尝试pop()
。
似乎Enqueue
可能会唤醒PrepDequeue
。
我的建议:
PrepDequeue
您可能还想查看此实现:concurrent_queue.hpp