弱参照を回避するという提案は、レースの問題を解決しません。
T1 operator new, create object, references: 1
T1 passes interface object reference to T2, thinking it can "share" ownership
T1 suspends
T2 resumes
T2 QueryInterface
T2 suspends before InterlockedIncrement, references: 1
T1 resumes
T1 Calls Release
T1 suspends between InterlockedDecrement and operator delete, references: 0
T2 resumes, InterlockedIncrement occurs, references 1
T2 suspends
T1 resumes, operator delete executes, references 1 !!!
T1 suspends
T2 resumes
T2 Any reference to the interface is now invalid since it has been deleted with reference count 1.
これはCOMサーバーで解決できます。ただし、COMクライアントは、この競合状態を防ぐサーバーに依存しないようにする必要があります。したがって、COMクライアントはスレッド間でインターフェイスオブジェクトを共有してはなりません(MUSTNOT)。インターフェイスオブジェクトへのアクセスを許可する必要がある唯一のスレッドは、現在インターフェイスオブジェクトを「所有」している1つのスレッドです。
T1はリリースを呼び出すべきではありませんでした。はい、インターフェイスオブジェクトをT2に渡す前にAddRefを呼び出すことができます。しかし、それはレースを解決しないかもしれません、それをどこかに移動するだけです。ベストプラクティスは、常に1つのインターフェイスオブジェクト、1つの所有者の概念を維持することです。
COMサーバーが2つ(またはそれ以上)のインターフェースが共有サーバー内部状態を参照できるという概念をサポートしたい場合、COMサーバーはCreateCopyOfInstanceメソッドを提供してコントラクトをアドバタイズし、内部で競合を管理する必要があります。もちろん、この種の「ファンアウト」を処理するサーバーの例もあります。Microsoftの永続ストレージインターフェイスを見てください。そこでは、インターフェースは「ファンアウト」しません。各インターフェースは単一のユーザー(スレッド/プロセス/その他)が所有する必要があり、「ファンアウト」はサーバーによって内部的に管理され、メソッドが提供されます。競合の問題のいくつかの側面を制御するCOMクライアント。したがって、MicrosoftのCOMサーバーは、クライアントとの契約の一部として競合状態に対処する必要があります。