私は現在、モノスレッドプログラムをマルチスレッドに渡そうとしています。このソフトウェアは「refCounted」オブジェクトを大量に使用するため、マルチスレッドでいくつかの問題が発生します。私の問題を解決するデザインパターンや何かを探しています。
主な問題は、スレッド間のオブジェクトの削除です。通常、削除は参照カウントを減らすだけであり、refcount がゼロに等しい場合、オブジェクトは削除されます。これはモノスレッド プログラムでうまく機能し、ビッグ オブジェクトのコピーでパフォーマンスを大幅に向上させることができます。
ただし、マルチスレッドでは、オブジェクトがミューテックスによって保護されているため、2 つのスレッドが同じオブジェクトを同時に削除したい場合があります。1 つのスレッドだけがオブジェクトを削除し、もう 1 つのスレッドをブロックします。しかし、ミューテックスを解放すると、他のスレッドは無効な (解放されたオブジェクト) で実行を継続し、メモリの破損につながります。
このクラス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
};
2 つのスレッドが同じ RefCountedObject を削除したいとします。どちらも ~RefCountedObject にあり、Destroy() を呼び出します。最初のスレッドはミューテックスをロックしており、もう 1 つのスレッドは待機しています。最初のスレッドによってオブジェクトが削除された後、2 番目のスレッドはその実行を継続し、空きメモリへの書き込みを引き起こします。
誰もが同様の問題を経験し、解決策を見つけましたか?
助けてくれてありがとう、私は私の間違いに気づきました: ミューテックスは refCount 自体ではなく、refCount ポインターのみを保護しています! ミューテックスで保護された RefCount クラスを作成しました。ミューテックスは、すべての refCounted オブジェクト間で共有されるようになりました。
今はすべて正常に動作します。