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的必需参数。谢谢