COM オブジェクトの AddRef メソッドと Release メソッドの内部でインターロック API が使用され、スレッドセーフな参照カウントをインクリメント/デクリメントすることを知っています。しかし、ここで理解しようとしているのは、Interlock API を十分に使用しているか、Mutex などの他の同期オブジェクトも必要であるということです。これまでに見たすべてのサンプル コードは、Interlock API のみを使用していました。
シナリオ- メッセージ オブジェクトの AddRef メソッドと Release メソッドを次のように実装したとします。スレッド A がメッセージ オブジェクトにアクセスしているとします。そのため、 m_lRef カウントは 1 です。メッセージ オブジェクトの使用が完了すると、スレッド A が Release メソッドを呼び出します。
内部リリース方法 – 9 行目 - m_lRef = 1 10 行目 - m_lRef = 0、lRef = 0
スレッド A は 10 行目で中断し、別のスレッド B が同じメッセージにアクセスするため、3 行目で m_lRef 値の値を 1 に設定する AddRef メソッドを呼び出します。ここで、スレッド B が中断され、スレッド A が行 #11 – m_lRef =1, lRef = 0 で再開されます。スレッド A はオブジェクトを削除します。スレッド B が同じオブジェクトにアクセスしようとすると、クラッシュは避けられません。
私の質問- 私のシナリオは有効ですか? m_lRef =1 の場合、他のスレッドがオブジェクトへのアクセスを待機していないことが理想的です。しかし、そのような予期しないシナリオでのクラッシュを防ぐために、解放方法全体をミューテックスまたは CS で保護するべきではありませんか?
1. STDMETHODIMP_(ULONG) CMapiMsg::AddRef()
2. {
3. LONG lRef = InterlockedIncrement(&m_lRef);
4. return lRef;
5. }
6.
7. STDMETHODIMP_(ULONG) CMapiMsg::Release()
8. {
9. LONG lRef = InterlockedDecrement(&m_lRef);
10. if(0 == lRef)
11. {
12. delete this;
13. }
14. return lRef;
15. }