C++ 不同线程之间的互斥锁同步
由于我最近开始编写多线程程序,这可能是一个愚蠢的问题。我发现了非常棒的互斥和条件变量用法。据我所知,有以下用途:C++ 不同线程之间的互斥锁同步,c++,multithreading,mutex,condition-variable,boost-mutex,C++,Multithreading,Mutex,Condition Variable,Boost Mutex,由于我最近开始编写多线程程序,这可能是一个愚蠢的问题。我发现了非常棒的互斥和条件变量用法。据我所知,有以下用途: 保护代码/共享资源的部分不被多线程访问损坏。因此,锁定该部分,这样就可以控制访问哪个线程 如果一个线程正在等待另一个线程的资源/条件,那么可以使用cond.wait()而不是每毫秒轮询一次 现在考虑下面的类例子: class Queue { private: std::queue<std::string> m_queue; boost::mutex m_
现在考虑下面的类例子:
class Queue {
private:
std::queue<std::string> m_queue;
boost::mutex m_mutex;
boost::condition_variable m_cond;
bool m_exit;
public:
Queue()
: m_queue()
, m_mutex()
, m_cond()
, m_exit(false)
{}
void Enqueue(const std::string& Req)
{
boost::mutex::scoped_lock lock(m_mutex);
m_queue.push(Req);
m_cond.notify_all();
}
std::string Dequeue()
{
boost::mutex::scoped_lock lock(m_mutex);
while(m_queue.empty() && !m_exit)
{
m_cond.wait(lock);
}
if (m_queue.empty() && m_exit) return "";
std::string val = m_queue.front();
m_queue.pop();
return val;
}
void Exit()
{
boost::mutex::scoped_lock lock(m_mutex);
m_exit = true;
m_cond.notify_all();
}
}
类队列{
私人:
std::队列m_队列;
boost::mutex m_mutex;
boost::条件变量m_cond;
布尔穆出口;
公众:
队列()
:m_queue()
,m_mutex()
,m_cond()
,m_退出(错误)
{}
无效排队(常量std::string&Req)
{
boost::mutex::作用域锁定(m_mutex);
m_队列推送(Req);
m_cond.notify_all();
}
std::字符串出列()
{
boost::mutex::作用域锁定(m_mutex);
while(m_queue.empty()&&&!m_exit)
{
m_cond.wait(锁定);
}
if(m_queue.empty()&&m_exit)返回“”;
std::string val=m_queue.front();
m_queue.pop();
返回val;
}
无效退出()
{
boost::mutex::作用域锁定(m_mutex);
m_exit=true;
m_cond.notify_all();
}
}
在上面的示例中,可以调用Exit(),它将通知等待出列的线程,该退出了,而不必等待队列中的更多数据。
我的问题是,既然Dequeue已经获得了锁(mumutex),那么如何才能退出获取相同的锁(mumutex)?除非退出队列释放锁,否则只有退出才能获得它吗
我在析构函数实现中也看到过这种模式,使用相同的类成员互斥体,析构函数通知所有线程(类方法),到了终止它们各自的循环/函数等的时候了。正如Jarod在注释中提到的,调用
m_cond.wait(lock)
保证自动解锁互斥锁,为线程释放互斥锁,并开始侦听条件变量的通知(参见示例)。
这种原子性还确保线程中的任何代码在设置侦听后执行(因此不会错过任何通知调用)。当然,这假设线程首先锁定互斥锁,否则所有赌注都被取消
另一个需要了解的重要方面是,条件变量可能会受到“”的影响,因此有第二个布尔条件(例如,在这里,您可以检查队列的空性)很重要,这样您就不会被一个空队列唤醒。大概是这样的:
m_cond.wait(lock, [this]() { return !m_queue.empty() || m_exit; });
正如Jarod在评论中提到的,电话
m_cond.wait(lock)
保证自动解锁互斥锁,为线程释放互斥锁,并开始侦听条件变量的通知(参见示例)。
这种原子性还确保线程中的任何代码在设置侦听后执行(因此不会错过任何通知调用)。当然,这假设线程首先锁定互斥锁,否则所有赌注都被取消
另一个需要了解的重要方面是,条件变量可能会受到“”的影响,因此有第二个布尔条件(例如,在这里,您可以检查队列的空性)很重要,这样您就不会被一个空队列唤醒。大概是这样的:
m_cond.wait(lock, [this]() { return !m_queue.empty() || m_exit; });
有
m_条件等待(锁定)代码>释放锁。将锁传递给等待呼叫。它将在等待前解锁互斥锁。文档非常清楚,有m_cond.wait(lock)代码>释放锁。将锁传递给等待呼叫。它将在等待之前解锁互斥锁。文档非常清楚,谢谢Jarod、super和rubenvb。这很微妙。很高兴知道!我添加了一个很重要的一点(线程需要锁定互斥锁),否则当然没有足够的同步。这一切都很微妙,很容易出错(但一旦你明白了发生了什么,我也很容易纠正)。我建议将它(正如您所做的)包装在一个固定的界面中,这样在“队列”组件完成后您就不必担心这些细节了。谢谢Jarod、super和rubenvb。这很微妙。很高兴知道!我添加了一个很重要的一点(线程需要锁定互斥锁),否则当然没有足够的同步。这一切都很微妙,很容易出错(但一旦你明白了发生了什么,我也很容易纠正)。我建议将它(正如您所做的)包装在一个固定的接口中,这样您就不必在“队列”组件完成后担心这些细节。