1

我当前的代码看起来像这样

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();
}

一切都很好,除了onAgentUpdate每 1 秒调用大约一百万次时,我不得不担心性能和优化。

所以我想如果我更改执行检查的wait(lock)totimed_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和它自己的对象,因此使用与REGISTERED_AGENTS相同的方法进行迭代)mutexallAgentUpdatesDone()containermutex

4

2 回答 2

2

我对 C++11 原子不是很熟悉,但在 Solaris 上,您可以像这样使用 volatile bool 和 membar 操作的组合

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;
}

谢谢尼拉吉·拉蒂

于 2013-09-19T06:12:03.930 回答
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

于 2013-09-19T06:33:26.530 回答