【发布时间】:2010-12-26 15:47:50
【问题描述】:
我知道,我知道,我的邮件标题可能看起来很挑衅,因为 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 来完成?
谢谢!
【问题讨论】:
-
为什么你的对象被破坏了,而另一个线程仍然有指向它的指针?
-
不直接回答问题,你能取消注册引发
OnTimer()调用作为你的析构函数的第一步吗?当然,调用仍然可以“同时”异步进行,但目前尚不清楚为什么这个正在销毁的对象仍然是这些回调的目标。 -
@Anon :同意,这是代码异味。不过,我仍然对答案感兴趣。 @Seh:您的评论基于相同的代码气味。但是,我不能在不破坏封装的情况下直接取消它。
-
要考虑的另一种替代方法:忘记互斥锁并定义一个状态模型,您可以在其中移动原子转换,例如 Java 库的
FutureTask类。定义一个枚举状态模型,包括ALIVE、DESTRUCTING和DESTRUCTED(可能)。进入析构函数后,以原子方式将状态更改为 DESTRUCTING(如果您偏执,则通过 CAS),并(可能)在退出析构函数时将其更改为DESTRUCTED。在OnTimer()中,仅当状态为 ALIVE 时才执行工作。如果你需要阻止析构函数在OnTimer()运行时启动,你需要一个锁。