繁体   English   中英

手动释放增强锁?

[英]Manually releasing boost locks?

为了学习boost :: thread的组合,我正在为线程实现一个简单的屏障(BR)来锁定一个普通的互斥锁(M)。 但是,就我转到BR.wait()而言,互斥锁上的锁定没有释放,因此为了让所有线程都到达BR,需要手动释放M上的锁定。 所以我有以下代码:

boost::barrier BR(3);
boost::mutex M;

void THfoo(int m){
    cout<<"TH"<<m<<" started and attempts locking M\n";
    boost::lock_guard<boost::mutex> ownlock(M);

    cout<<"TH"<<m<<" locked mutex\n";
    Wait_(15); //simple wait for few milliseconds

    M.unlock(); //probably bad idea
    //boost::lock_guard<boost::mutex> ~ownlock(M);
    // this TH needs to unlock the mutex before going to barrier BR

    cout<<"TH"<<m<<" unlocked mutex\n";
    cout<<"TH"<<m<<" going to BR\n";
    BR.wait();
    cout<<"TH"<<m<<" let loose from BR\n";
}

int main()  
{  
    boost::thread TH1(THfoo,1);
    boost::thread TH2(THfoo,2);
    boost::thread TH3(THfoo,3);

    TH2.join(); //but TH2 might end before TH1, and so destroy BR and M
    cout<<"exiting main TH \n";

    return 0;  
}

而M.unlock()显然是一个糟糕的解决方案(不使用锁); 那么如何(简单地)释放锁? 另外:我如何(正确)在main()中等待所有线程完成? (TH2.join()很糟糕,因为TH2可能先完成......);

请不要建议复飞,例如使用条件变量,我也可以使用它,但必须可以在没有条件变量的情况下直接进行。

除了在块中确定boost::lock_guard范围之外,您还可以使用boost::unique_lock ,它可以显式unlock()

boost::unique_lock<boost::mutex> ownlock(M);

cout<<"TH"<<m<<" locked mutex\n";
Wait_(15); //simple wait for few milliseconds

ownlock.unlock();

如果您需要在以后重新获取互斥锁之前释放互斥锁,这将非常有用。

至于连接,只需依次调用所有线程句柄上的join()

就像是:

void THfoo(int m){
  // use a scope here, this means that the lock_guard will be destroyed (and therefore mutex unlocked on exiting this scope
  {
    cout<<"TH"<<m<<" started and attempts locking M\n";
    boost::lock_guard<boost::mutex> ownlock(M);

    cout<<"TH"<<m<<" locked mutex\n";
    Wait_(15); //simple wait for few milliseconds

  }
  // This is outside of the lock
  cout<<"TH"<<m<<" unlocked mutex\n";
  cout<<"TH"<<m<<" going to BR\n";
  BR.wait();
  cout<<"TH"<<m<<" let loose from BR\n";
}

至于等待,只需在所有线程句柄上调用join(如果它们已经完成,函数将立即返回)

TH1.join();
TH2.join();
TH3.join();

让它超出范围:

void THfoo(int m){
    cout<<"TH"<<m<<" started and attempts locking M\n";
    {
       boost::lock_guard<boost::mutex> ownlock(M);

       cout<<"TH"<<m<<" locked mutex\n";
       Wait_(15); //simple wait for few milliseconds
    }

    // this TH needs to unlock the mutex before going to barrier BR

    cout<<"TH"<<m<<" unlocked mutex\n";
    cout<<"TH"<<m<<" going to BR\n";
    BR.wait();
    cout<<"TH"<<m<<" let loose from BR\n";
}
cout<<"TH"<<m<<" started and attempts locking M\n";
{
    boost::lock_guard<boost::mutex> ownlock(M);

    cout<<"TH"<<m<<" locked mutex\n";
    Wait_(15); //simple wait for few milliseconds

} //boost::lock_guard<boost::mutex> ~ownlock(M);
// this TH needs to unlock the mutex before going to barrier BR

cout<<"TH"<<m<<" unlocked mutex\n";

只要您join所有线程,TH2首先完成时唯一的问题是TH1必须在TH2可以通过join “收获”之前完成运行,并且释放任何剩余资源(如返回值)。 3线程并不值得担心。 如果该内存使用是一个问题,那么你可以使用timed_join反复尝试所有线程。

您也可以执行您不想要的操作 - 让主线程在条件变量上等待,并且每个线程在完成时在某处存储一个值以表示它已完成,并发出条件变量的信号,以便主线程可以join它。 你必须绝对确定线程会发出信号,否则你可能会永远等待它。 如果你取消线程,要小心。

如果你使用boost :: mutex :: scoped_lock而不是boost :: lock_guard,它有一个unlock()方法。 如果你调用它,那么锁将不会尝试在其析构函数中重新解锁。 我发现代码更符合我的口味,而不是将锁放入自己的块中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM