オブジェクトの参照カウントがスレッドセーフであることを確認する方法について頭を悩ませようとしています。
class MyObject{
//Other implementation details
private:
mutable volatile LONGLONG * m_count;
IData * m_data;
};
必要なクラス宣言がそこにあると仮定して、単純にしておきます。コピー コンストラクタとデストラクタの実装を次に示します。
MyObject::MyObject(const MyObject& rhs) : m_count(rhs.m_count), m_data(rhs.m_data){
InterlockedIncrement64(m_count);
}
MyObject::~MyObject(){
if(InterlockedDecrement64(m_count) == 0)
delete m_data;
}
このスレッドは安全ですか? アトミックかどうかに関係なく、コピー コンストラクターの intilization リストはどのように表示されますか? それも問題ですか?初期化リストでカウントの増分値を設定する必要がありますか (これは可能ですか)?
このままで十分です。そうでなけれthread1
ばthread2
、count == 1
. スレッド間でハンドシェイクが必要です。つまり、スレッド 1 は、スレッド 2 のオブジェクトが範囲外になる前にオブジェクトを完全にコピーする必要があります。
これらの回答のいくつかを読んだ後、私は戻って少し調査を行いました. Boost は、非常によく似たように shared_ptr を実装しています。これがデストラクタの呼び出しです。
void release() // nothrow
{
if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
ブーストのドキュメントでは、割り当てはスレッドセーフではないと明確に述べていると示唆する人もいます。私は同意し、同意しません。私の場合、私は同意しないと思います。スレッド A とスレッド B の間のハンドシェイクのみが必要です。いくつかの返信で説明されている問題のいくつかは、ここでは当てはまらないと思います (ただし、それらは私が完全には考えていない目を見張るような返信でしたが)。
例 ThreadA atach(SharedObject); //値で渡された共有オブジェクト、カウントの増分など
ThreadB //オブジェクトを受け入れ、共有オブジェクトのリストに追加します。ThreadB は、すべての SharedObjects にイベントを通知するタイマー上にあります。通知する前に、クリティカル セクションによって保護されたリストのコピーが作成されます。CS がリリースされ、コピーが通知されます。
ThreadA detach(SharedObject); //オブジェクトのリストから共有オブジェクトを削除します
現在、同時に ThreadB は SharedOjbect をシグナリングしており、ThreadA が共有オブジェクトをデタッチする前にリストのコピーを作成しています。すべて大丈夫ですよね?