C++ 这是使用不带互斥的条件变量的安全方法吗

C++ 这是使用不带互斥的条件变量的安全方法吗,c++,locking,mutex,condition-variable,C++,Locking,Mutex,Condition Variable,我当前的代码如下所示 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 = c

我当前的代码如下所示

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();
}
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;
}
问题是:这安全吗

多谢各位

一个小提示:
假设这两个函数中的其余操作已经由它们自己的互斥锁保护(
REGISTERED_AGENTS
是一个类对象,它有一个
容器
,并且在每个访问器和迭代方法中调用它自己的
mutex
,因此
allAgentUpdatesDone()
使用与注册代理相同的
互斥体在相同的
容器中进行迭代)

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

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();
}
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;
}
volatile bool done=false;
void XXX::waitForUpdates()
{
//boost::唯一的锁(互斥锁);
而(!allAgentUpdatesDone()){
而(!完成)
{
美国LEEP(1000000);
membar_consumer();
}
}
}
void XXX::onAgentUpdate(YYY参数){
Agent*target=const_cast(argums.GetAgent());
//boost::唯一的锁(互斥锁);
membar_producer();
注册代理。setDone(target,true);
完成=正确;
}
谢谢
Niraj Rathi

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

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();
}
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;
}
volatile bool done=false;
void XXX::waitForUpdates()
{
//boost::唯一的锁(互斥锁);
而(!allAgentUpdatesDone()){
而(!完成)
{
美国LEEP(1000000);
membar_consumer();
}
}
}
void XXX::onAgentUpdate(YYY参数){
Agent*target=const_cast(argums.GetAgent());
//boost::唯一的锁(互斥锁);
membar_producer();
注册代理。setDone(target,true);
完成=正确;
}
谢谢 Niraj Rathi

您可以这样做:

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();
}
void XXX::waitForUpdates()
{
boost::唯一的锁(互斥锁);
而(!allAgentUpdatesDone()){
++服务员;
条件变量代理完成。等待(锁定);
--服务员;
}
}
void XXX::onAgentUpdate(YYY参数){
Agent*target=const_cast(argums.GetAgent());
boost::唯一的锁(互斥锁);
注册代理。setDone(target,true);
如果(服务员!=0)
COND_VAR_AGENT_DONE.notify_all();
}
互斥锁保护
服务员
计数。确保将其设置为零以启动

您可能希望condition变量已经有类似的内容,但是调用
notify\u all
的开销可能非常大

这假设大部分时间没有服务员。如果问题是大部分时间
allAgentUpdatesDone
返回
false
,则不要调用
notify\u all
,除非所有更新都已完成。

您可以这样做:

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();
}
void XXX::waitForUpdates()
{
boost::唯一的锁(互斥锁);
而(!allAgentUpdatesDone()){
++服务员;
条件变量代理完成。等待(锁定);
--服务员;
}
}
void XXX::onAgentUpdate(YYY参数){
Agent*target=const_cast(argums.GetAgent());
boost::唯一的锁(互斥锁);
注册代理。setDone(target,true);
如果(服务员!=0)
COND_VAR_AGENT_DONE.notify_all();
}
互斥锁保护
服务员
计数。确保将其设置为零以启动

您可能希望condition变量已经有类似的内容,但是调用
notify\u all
的开销可能非常大


这假设大部分时间没有服务员。如果问题是大部分时间
allAgentUpdatesDone
返回
false
,那么不要调用
notify\u all
,除非所有更新都完成。

在第二个版本的
waitForUpdates()
代码中省略互斥锁是错误吗?因为该代码中没有
lock
变量,我假设
lock
不是成员。假设您修复了这个问题,如果
setDone
是原子的,并且服务生对应的
getDone
谓词检查也是原子的,那么您不需要在设置之前等待`onAgentUpdate中的互斥体,但在更改之后仍然需要通知。(所有这些都假设我遵循了你的代码,这对于所有的抽象来说并不容易)。@WhozCraig哦,对不起,是的,肯定有一个锁变量。它是timed_wait的必需参数。谢谢,现在就改。好的。我事后说的有道理吗?它取决于该成员国的get/set的原子性。如果它是无锁原子的,那么它可以工作(顺便说一句,您应该检查您的定时等待结果)。但是,如果您希望条件等待因超时以外的原因而出现,则仍然需要通知。如果没有这一点,它可能只是一个睡眠。你说的“安全”是什么意思?你的问题很难理解。如果你的问题是,“我可以用一个条件变量作为一种愚蠢的方式来释放一个锁,等待一段指定的时间,然后重新获取该锁吗?”当然,你可以。@WhozCraig,我想是的。您所说的
state member
是指
lock
成员right?在第二版本的
waitForUpdates()
code中遗漏了互斥锁是错误的吗?因为该代码中没有
lock
变量,我假设
lock
不是成员。假设您修复了这个问题,如果
setDone
是原子的,并且服务生对应的
getDone
谓词检查也是原子的,那么您不需要在设置之前等待`onAgentUpdate中的互斥体,但在更改之后仍然需要通知。(所有这些都假设我遵循了你的代码,这对于所有的抽象来说并不容易)。@WhozCraig哦,对不起,是的,肯定有一个锁变量。它是timed_wait的必需参数。谢谢