我目前的代码如下所示
void XXX::waitForUpdates()
{
boost::unique_lock<boost::mutex> lock(mutex_agentDone);
while(!allAgentUpdatesDone()) {
COND_VAR_AGENT_DONE.wait(lock);
}
}
void XXX::onAgentUpdate(YYY argums){
Agent * target = const_cast<Agent*>(argums.GetAgent());
boost::unique_lock<boost::mutex> lock(mutex_agentDone);
REGISTERED_AGENTS.setDone(target,true);
COND_VAR_AGENT_DONE.notify_all();
}
一切都很好,除非每1秒调用onAgentUpdate
一百万次,我不得不担心性能和优化。
所以我想如果我将wait(lock)
更改为执行timed_wait
检查的allAgentUpdatesDone()
版本,我可以跳过.notify()
s,否则会以数百的顺序调用每秒数千!不要喘息,这是一个模拟框架:)
然后我问myseld:我需要mutex_agentDone
为什么?我可以修改这两个函数:
void XXX::waitForUpdates()
{
//this lock will become practically useless, coz there is no other
// mutex_agentDone being locked in any other function.
boost::unique_lock<boost::mutex> lock(mutex_agentDone);
while(!allAgentUpdatesDone()) {
COND_VAR_AGENT_DONE.timed_wait(lock,some_time_interval);
}
}
void XXX::onAgentUpdate(YYY argums){
Agent * target = const_cast<Agent*>(argums.GetAgent());
REGISTERED_AGENTS.setDone(target,true)
}
问题是:这样安全吗?
谢谢
小记:
假设两个函数中的其余操作已经由它们自己的互斥锁保护(REGISTERED_AGENTS
是一个类对象,在每个访问器和迭代方法中调用container
并调用自己的mutex
,因此allAgentUpdatesDone()
使用相同的container
和REGISTERED_AGENTS迭代相同的mutex
答案 0 :(得分:2)
我不太熟悉C ++ 11原子,但在Solaris上你可以使用volatile bool和membar ops这样的组合
volatile bool done = false;
void XXX::waitForUpdates()
{
// boost::unique_lock<boost::mutex> lock(mutex_agentDone);
while(!allAgentUpdatesDone()) {
while ( !done )
{
usleep(1000000);
membar_consumer();
}
}
}
void XXX::onAgentUpdate(YYY argums){
Agent * target = const_cast<Agent*>(argums.GetAgent());
//boost::unique_lock<boost::mutex> lock(mutex_agentDone);
membar_producer();
REGISTERED_AGENTS.setDone(target,true);
done = true;
}
由于 Niraj Rathi
答案 1 :(得分:2)
你可以这样做:
void XXX::waitForUpdates()
{
boost::unique_lock<boost::mutex> lock(mutex_agentDone);
while(!allAgentUpdatesDone()) {
++waiters;
COND_VAR_AGENT_DONE.wait(lock);
--waiters;
}
}
void XXX::onAgentUpdate(YYY argums){
Agent * target = const_cast<Agent*>(argums.GetAgent());
boost::unique_lock<boost::mutex> lock(mutex_agentDone);
REGISTERED_AGENTS.setDone(target,true);
if (waiters != 0)
COND_VAR_AGENT_DONE.notify_all();
}
互斥锁保护waiters
计数。确保将其设置为零才能启动。
你会期望条件变量已经有类似的东西,但只是调用notify_all
的开销可能很大。
这假定大部分时间没有服务员。如果问题是大部分时间allAgentUpdatesDone
都会返回false
,那么除非所有更新完成,否则请不要致电notify_all
。