gpt4 book ai didi

c++ - 与 boost::condition_variable 的线程同步

转载 作者:太空宇宙 更新时间:2023-11-04 13:56:43 25 4
gpt4 key购买 nike

我目前使用的是 boost 1.55.0,我不明白为什么这段代码不起作用。

下面的代码是一个简化,与我的程序有同样的问题。小的运行完成,但当它们更大时,线程会永远等待。

boost::mutex m1;
boost::mutex critical_sim;

int total= 50000;

class krig{

public:

float dokrig(int in,float *sim, bool *aux, boost::condition_variable *hEvent){

float simnew=0;

boost::mutex::scoped_lock lk(m1);

if (in > 0)
{
while(!aux[in-1]){
hEvent[in-1].wait(lk);
}
simnew=1+sim[in-1];

}

return simnew;
};

};

void Simulnode( int itrd,float *sim, bool *aux, boost::condition_variable *hEvent){
int j;
float simnew;

krig kriga;

for(j=itrd; j<total; j=j+2){

if (fmod(1000.*j,total) == 0.0){
printf (" .progress. %f%%\n",100.*(float)j/(float)total);
}

simnew= kriga.dokrig(j,sim, aux, hEvent);

critical_sim.lock();
sim[j]=simnew;
critical_sim.unlock();

aux[j]=true;
hEvent[j].notify_one();
}
}


int main(int argc, char* argv[])
{
int i;
float *sim = new float[total];

bool *aux = new bool[total];

for(i=0; i<total; ++i)
aux[i]=false;

//boost::mutex m1;

boost::condition_variable *hEvent = new boost::condition_variable[total];

boost::thread_group tgroup;
for(i=0; i<2; ++i) {
tgroup.add_thread(new boost::thread(Simulnode, i,sim, aux, hEvent));

}
tgroup.join_all();

return 0;
}

奇怪的是,我注意到如果我将 dokrig() 内联的代码放在 simulnode() 中,那么它似乎可以工作。会不会是锁的范围有问题?

谁能告诉我哪里错了?提前致谢。

最佳答案

问题发生在这部分:

aux[j]=true;
hEvent[j].notify_one();

第一行表示由 hEvent 条件变量监视的条件的变化。第二行向消费者部分声明了此更改,即等待条件变为真。

问题是这两个步骤在没有与消费者同步的情况下发生,这可能导致以下竞争:

  • 消费者检查当前为假的条件。这发生在受互斥锁 m1 保护的关键部分。
  • 发生线程切换。生产者将条件更改为真并通知所有等待的消费者。
  • 线程切换回来。消费者恢复并调用等待。然而,他已经错过了最后一步发生的通知,所以他将永远等待。

重要的是要了解传递给条件变量的 wait 调用的互斥量的目的不是保护条件变量本身,而是保护它监视的 条件(在本例中是对 aux 的更改)。

为避免数据竞争,写入aux 和随后的通知必须由相同的互斥锁保护:

{
boost::lock_guard<boost::mutex> lk(m1);
aux[j]=true;
hEvent[j].notify_one();
}

关于c++ - 与 boost::condition_variable 的线程同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21146998/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com