【发布时间】:2012-06-29 21:18:43
【问题描述】:
我想让一个线程等待另一个线程销毁特定对象。我想过以某种方式实现它:
class Foo {
private:
pthread_mutex_t* mutex;
pthread_cond_t* condition;
public:
Foo(pthread_mutex_t* _mutex, pthread_cond_t* _condition) : mutex(_mutex), condition(_condition) {}
void waitForDestruction(void) {
pthread_mutex_lock(mutex);
pthread_cond_wait(condition,mutex);
pthread_mutex_unlock(mutex);
}
~Foo(void) {
pthread_mutex_lock(mutex);
pthread_cond_signal(condition);
pthread_mutex_unlock(mutex);
}
};
然而,我知道我必须在 waitForDestruction 方法中处理虚假唤醒,但我不能在 'this' 上调用任何东西,因为它可能已经被破坏了。
我想到的另一种可能性是不使用条件变量,而是在构造函数中锁定互斥锁,在析构函数中解锁它并在 waitForDestruction 方法中锁定/解锁它 - 这应该适用于非递归互斥锁,而iirc我可以从一个没有锁定它的线程中解锁一个互斥锁,对吧?第二种选择是否会受到任何虚假唤醒的影响?
【问题讨论】:
-
抛开设计不谈,如果你让构造函数创建互斥锁和条件,而不是作为参数传递,它们对于每个实例都是唯一的,你不必担心杂散信号。但是,您需要有适当的复制构造函数和赋值运算符来创建新的互斥体/条件。
-
忘记缺少的
while循环,您根本无法像那样实现waitForDestruction。您要求对象检查它是否存在。您需要将同步拆分为另一个对象。 -
我认为您应该考虑创建一个单独的对象,第一个线程等待该对象并触发相关对象的析构函数。
-
@all - 是的,我知道这是糟糕的设计,这个问题更多的是出于兴趣而不是出于实际实施它的需要。 @Joachim,我认为这会引入更多问题,例如在
waitForDestruction中等待的线程访问互斥锁时必须销毁析构函数中的互斥锁。 @Potatoswatter:嗯,你是对的,如果在对象被破坏后调用waitForDestruction,就会出现竞争条件。这很糟糕,可能无法修复。我想你不应该做那样的事情是有原因的:) -
嗯,另一个想法:是否可以使用容量为 1 的信号量(在
Foo之外创建),在 ctor 中抓取,在 dtor 中释放。然后调用线程可以尝试获取信号量并将阻塞直到Foo释放它。 @Tom:基本上是您的想法,我认为为此目的使用信号量就可以了
标签: c++ synchronization pthreads conditional-statements