boost::mutex / 如何测试互斥锁是否被锁定

问题描述 投票:0回答:4

我知道,我知道,我的消息标题可能看起来具有挑衅性,因为 boost::mutex 有目的地不公开锁定/解锁(以避免死锁)。

然而,Boost 文档在这些方面非常简短(至少可以这么说),所以我问是否有人可以在以下用例中帮助我。

假设你有一个 Foo 类,其中有:
- 需要一些时间才能完成的析构函数
- 由不同线程调用的方法,但不应在销毁期间调用

class Foo
{
 public:

  virtual ~Foo()
  { 
    //Time consuming operations here
  }


  //Method called by a timer belonging to a distinct class 
  void OnTimer()
  {
    //Other time consuming stuff. Should not be called during destruction !
  }  


}; 

我尝试(没有成功)实现一个基于 boost::mutex 的版本

//boost::mutex implementation
class Foo
{
public:
  Foo()
  {
  }

  virtual ~Foo()
  { 
    {
      boost::mutex::scoped_lock lock(mDisposingMutex);
      //Time consuming operations here
    }
  }


  //Method called by a timer belonging to a distinct class 
  void OnTimer()
  {
    {
      //Imaginary code here: mutex::locked() method is private !!!
      if ( ! mDisposingMutex.locked()) 
        return;
    }    
    //Other time consuming stuff. Should not be called during destruction !
  }  

private:
  boost::mutex mDisposingMutex; 
}; 

我完全错了吗?谁能告诉我如何使用 boost::mutex 来完成此操作?

谢谢!

boost mutex
4个回答
6
投票

如果您确实承诺在析构函数体中使用

Lockable::lock()
,则可以让您的
OnTimer()
函数使用
Lockable::try_lock()
,并且仅当该函数返回 true 时才继续。如果
OnTimer()
首先启动,那么
OnTimer()
会暂停析构函数,但是它 still 并不能解决析构函数运行、完成并释放互斥锁,然后
OnTimer()
启动并成功抓取互斥锁的问题。互斥锁。

这样的序列很可能属于未定义行为的领域,但诅咒不会阻止它发生。除了互斥锁之外,使用状态标志 - 类似于我在上面的评论中描述的 - 可以让您检测到后一种情况,并阻止 OnTimer()

 执行除读取标志之外的任何操作。但在某些时候,这只是将创可贴放在创可贴之上。


4
投票
@Seh:我完全同意这是一种代码味道,我应该(并且将会)纠正根本原因。

但是,为了帮助任何遇到与我相同问题的人(即与 boost 文档斗争),我尝试实施你的建议。 下面的代码现在可以正确编译(尽管代码味道现在非常强烈)

#include <boost/thread/mutex.hpp> //boost::mutex implementation class Foo { public: Foo() : mIsDisposing(false) { } virtual ~Foo() { { boost::try_mutex::scoped_try_lock lock(mDisposingMutex); if ( ! lock.locked()) { //Die by horrible death, or wait before trying again... } else { mIsDisposing = true; } //Time consuming operations here } } //Method called by a timer belonging to a distinct class void OnTimer() { { boost::try_mutex::scoped_try_lock lock(mDisposingMutex); if ( ! lock.locked() || mIsDisposing ) { return; } } //Other time consuming stuff. Should not be called during destruction ! } private: boost::try_mutex mDisposingMutex; bool mIsDisposing; };
    

2
投票
互斥体::try_lock()


0
投票
这里的核心问题是试图保护你的互斥体是被破坏的对象的一部分。考虑这样一种情况,您在析构函数释放互斥体后

立即检查对象,不再有对象,只有未定义的行为。 相反,您应该在类中拥有互斥体(例如

Bar

),该互斥体引用了

Foo
,以及类似
void Bar::DeleteFoo() {
   {
     boost::some_lock<boost::mutex> lock(myFooMutex);
     auto delete_me = myFoo;
     myFoo = nullptr;
   }
   delete delete_me;
}

Bar::OnTime()

在调用

Foo::OnTimer()
 时将获取并保存相同的互斥锁
    

© www.soinside.com 2019 - 2024. All rights reserved.