Ste*_*ury 7 c++ multithreading refcounting
我目前正在尝试将单线程程序传递给多线程.该软件大量使用"refCounted"对象,这导致多线程中的一些问题.我正在寻找一些可能解决我的问题的设计模式.
主要问题是线程之间的对象删除,通常删除只减少引用计数,当refcount等于零时,则删除对象.这在monothread程序中运行良好,并且可以通过大对象的副本实现一些很好的性能提升.
但是,在多线程中,两个线程可能希望同时删除同一个对象,因为该对象受互斥锁保护,只有一个线程删除该对象并阻塞另一个.但是当它释放互斥锁时,另一个线程继续执行无效(释放对象),这会导致内存损坏.
以下是此类RefCountedObject的示例
class RefCountedObject
{
public:
RefCountedObject()
: _refCount( new U32(1) )
{}
RefCountedObject( const RefCountedObject& obj )
: _refCount( obj._refCount )
{
ACE_Guard< ACE_Mutex > guard( _refCountMutex );
++(*_refCount);
}
~RefCountedObject()
{
Destroy();
}
RefCountedObject& operator=( const RefCountedObject& obj )
{
if( this != &obj )
{
Destroy();
ACE_Guard< ACE_Mutex > guard( _refCountMutex );
_refCount = obj._refCount;
++(*_refCount);
}
return *this;
}
private:
void Destroy()
{
ACE_Guard< ACE_Mutex > guard( _refCountMutex ); // thread2 are waiting here
--(*_refCount); // This cause a free memory write by the thread2
if( 0 == *_refCount )
delete _refCount;
}
private:
mutable U32* _refCount;
mutable ACE_Mutex _refCountMutex; // BAD: this mutex only protect the refCount pointer, not the refCount itself
};
Run Code Online (Sandbox Code Playgroud)
假设两个线程想要删除相同的RefCountedObject,两者都在~RefCountedObject中并调用Destroy(),第一个线程锁定了互斥锁,另一个线程正在等待.在第一个线程删除对象之后,第二个线程将继续执行并导致空闲内存写入.
任何人都有类似问题的经验,并找到了解决方案?
感谢大家的帮助,我意识到自己的错误:互斥锁只是保护refCount指针,而不是refCount本身!我创建了一个受互斥保护的RefCount类.现在,所有refCounted对象之间共享互斥锁.
现在一切正常.
如果计数是对象的一部分,那么如果一个线程可能尝试增加引用计数,而另一个线程尝试删除最后一个引用,那么您就会遇到一个固有的问题。对于每个可全局访问的对象指针,引用计数上需要有一个额外的值,因此,如果您有指针,则始终可以安全地增加引用计数。
一种选择是使用boost::shared_ptr (请参阅文档)。您可以使用自由函数atomic_load、atomic_store和atomic_exchange(atomic_compare_exchange文档中明显没有这些函数)来确保在访问共享对象的全局指针时得到适当的保护。一旦您的线程获得了shared_ptr对特定对象的引用,您就可以使用普通的非原子函数来访问它。
另一种选择是使用 Joe Seigh 的atomic_ptr_plus 项目中的原子引用计数指针