我目前正在尝试将单线程程序传递给多线程。该软件大量使用“refCounted”对象,这导致了多线程中的一些问题。我正在寻找一些设计模式或可能解决我的问题的东西。
主要问题是线程之间的对象删除,通常删除只会减少引用计数,当 refcount 等于 0 时,则删除对象。这在单线程程序中运行良好,并且可以通过复制大对象来提高性能。
但是,在多线程中,两个线程可能希望同时删除同一个对象,因为该对象受互斥锁保护,只有一个线程删除该对象并阻止另一个。但是当它释放互斥锁时,另一个线程继续执行无效(释放的对象),这会导致内存损坏。
这是此类 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
};
假设两个线程要删除同一个 RefCountedObject,都在 ~RefCountedObject 中并调用 Destroy(),第一个线程已锁定互斥体,另一个正在等待。在第一个线程删除对象后,第二个线程将继续执行并导致空闲内存写入。
任何人都有类似问题的经验并找到了解决方案?
感谢大家的帮助,我意识到我的错误:互斥锁只保护 refCount 指针,而不是 refCount 本身!我创建了一个受互斥保护的 RefCount 类。互斥锁现在在所有 refCounted 对象之间共享。
现在一切正常。