从多线程程序中安全地删除对象
Delete an object securely from a multi-threaded program
免责声明:既不允许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实例并进行操作在多个线程中使用它。然后我想安全地删除它,这样这些线程不会陷入分段故障。
您不能删除正在使用的对象。再多的互斥也无法解决这个问题。
我在Foo 中添加了一个析构函数
只有在删除Foo
时才会运行此操作。不过,它的内容并不重要:当其他线程仍在使用Foo时调用dtor是错误的。
我希望线程在删除实例时安全退出。这怎么可能?
好吧,这是正确的问题。我可以写很多代码供您使用,但这些代码只是boost::weak_ptr
的副本。所以,我就不麻烦了。你自己拿助推码就行了。
不允许Boost。
那你为什么要问StackOverflow?这基本上是相同的许可证。
这里缺少的是指示线程处理何时完成的条件。删除特定对象实例不是一个好条件。您还没有向我们显示删除对象的位置。如果我们能在代码中看到这一点,那么额外的上下文将很有帮助。
我建议不要删除对象,而是在对象上设置一个标志(例如bool-active())。然后,所有线程都将检查此标志,当它指示停止处理时,线程将停止。在当前正在删除Foo对象的位置设置此标志。然后,一旦所有线程都停止,就删除Foo对象。
如果删除对象并希望能够获取其互斥锁,则可能会出现崩溃,或者至少会出现不稳定的行为,因为互斥是Foo的成员,它将随对象一起销毁。
下面是我的意思的一个例子:
class Foo
{
public:
void lockMutex();
void unlockMutex();
// Active should be mutex protected as well
// Or you could consider using a pthread_rwlock
bool active() {return active_;}
void setActive(bool a) {active_ = a;}
private:
pthread_mutex_t mutex;
bool active_;
};
void* thread ( void* fooPtr )
{
Foo* fooPointer = (Foo*) fooPtr;
while ( 1 )
{
if ( fooPointer->active() )
{
fooPointer->lockMutex();
/* some code, involving fooPointer */
fooPointer->unlockMutex();
}
else
{
pthread_exit ( NULL );
}
}
// somewhere else in the code
fooPointer->setActive(false);
}
Foo::setActive(true)必须在构造函数中调用,或者在创建对象时调用。一旦线程停止,Foo对象就应该被删除,很可能是在pthread_join()完成之后。
您发布的代码是不对的,因为c++对象被步骤破坏:
obj->Foo::~Foo();
free memory //maybe delete if allocated by new
所以你的源只是对析构函数进行原型化,而不是对内存本身进行释放。
也许下面的源代码可以帮助你,它简单粗暴,但我认为它可以工作
class Foo
{
public:
void dosomething() {}
};
template<typename T>
class Protect
{
public:
struct auto_lock {
auto_lock(pthread_mutex_t& mutex)
: _mutex(mutex)
{
pthread_mutex_lock ( &_mutex );
}
~ auto_lock()
{
pthread_mutex_unlock ( &_mutex );
}
pthread_mutex_t& _mutex;
};
Protect(T*& p): _p(p) {}
T* get() { return _p; }
void lock() { pthread_mutex_lock ( &_mutex ); }
void unlock() { pthread_mutex_unlock ( &_mutex );}
pthread_mutex_t& getlock() { return _mutex; }
void safe_release() {
auto_lock l(_mutex);
if (_p != NULL) {
delete _p;
_p = NULL;
}
}
private:
T*& _p;
pthread_mutex_t _mutex;
};
void* thread ( void* proPtr )
{
Protect<Foo>* proPointer = (Protect<Foo>*) proPtr;
while ( 1 )
{
Protect<Foo>::auto_lock l(proPointer->getlock());
Foo* fooPtr = proPointer->get();
if ( fooPtr )
{
fooPtr->dosomething();
}
else
{
pthread_exit ( NULL );
}
}
}
- 迭代时从向量和内存中删除对象
- C++从对象自己的类中删除对象
- 如何通过对象的类属性删除对象,并返回其对象值?
- 删除对象(具有不同类型)的引用时会发生什么情况?
- 从列表C++中删除对象
- c++ 循环访问对象列表并删除对象
- 从对象本身的容器中删除对象
- 从尝试引用已删除函数的矢量 C++ 中删除对象
- 如何通过指向元组的共享指针删除对象
- 防止通过接口删除对象
- 在 c++ 中从内存中删除对象
- 当对象被删除时,复制被删除对象的对象如何
- 当我使用dynamic_cast并删除对象删除时,析构函数是如何工作的?
- 从内存中删除对象
- 通过C++中的删除方法自行删除对象
- C++ - 析构函数只是释放内存还是实际删除对象
- 如何通过存储在 std::list 中的指针删除对象?
- 如何通过对象参数从指针矢量中删除对象和指针
- 我可以删除对象的右值版本的函数吗?
- 使用对象的索引从矢量中删除对象