【发布时间】:2012-09-17 08:07:11
【问题描述】:
免责声明:既不允许 Boost,也不允许 C++11。
我有一个程序,我在其中创建了一个Foo 的实例,并在多个线程中对其进行操作。然后我想安全地删除它,这样那些线程就不会陷入分段错误。
我已向Foo 添加了一个互斥成员,并在每次线程函数运行时锁定它。为了不同的线程不会相互冲突。
class Foo
{
public:
pthread_mutex_t mutex;
};
void* thread ( void* fooPtr )
{
Foo* fooPointer = (Foo*) fooPtr;
while ( 1 )
{
if ( fooPointer )
{
pthread_mutex_lock ( &fooPointer->mutex );
/* some code, involving fooPointer */
pthread_mutex_unlock ( &fooPointer->mutex );
}
else
{
pthread_exit ( NULL );
}
}
}
现在我想安全地删除foo,这样线程中就不会发生错误。我给Foo添加了一个析构函数:
Foo::~Foo()
{
pthread_mutex_lock ( &mutex );
}
现在对象不会被删除,直到所有线程完成当前循环。
问题是:删除实例后互斥锁会被解锁吗?删除实例后所有线程都会结束吗?我敢打赌答案是no。所以我改变了析构函数,但现在它似乎是线程不安全的:
Foo::~Foo()
{
pthread_mutex_lock ( &mutex );
pthread_mutex_unlock ( &mutex );
}
线程函数能否在pthread_mutex_unlock ( &mutex );之后和对象被删除之前锁定互斥体并开始操作实例?
【问题讨论】:
-
您正在将
Foo传递给您的线程函数,因此,为什么不在所有线程完成运行后简单地删除对象呢?如果不是,您应该编写自己的shared_ptr版本,如上所述 -
或者只是...复制该死的标题。 boost 许可证允许您这样做(稍微不那么重要:RAII 是否也不允许?将其用于锁防护)
-
你的 if(fooPointer) 永远不会工作。没有人会因为 foo 对象被删除而将您的 fooPointer 设置为 NULL。如果您的应用程序确实需要线程之间的这种通信,您可以为此目的使用弱指针。
-
因为你已经围绕一个误解构建了一个解决方案,并且仅仅考虑到你做了什么,不可能推断出你应该做什么。
-
解决方案是自己实现 boost::shared_ptr 和 boost::weak_ptr !你的 fooPointer 需要是一个弱指针,故事结束。
标签: c++ multithreading thread-safety mutex delete-operator