Предложение избегать слабых ссылок не решает проблему гонки.
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-клиенты НЕ ДОЛЖНЫ совместно использовать объекты интерфейса между потоками.Единственный поток, которому должен быть разрешен доступ к объекту интерфейса, - это ОДИН поток, который в настоящее время «владеет» объектом интерфейса.
T1 НЕ должен был вызывать Release.Да, он мог вызвать AddRef до передачи объекта интерфейса в T2.Но это может не решить гонку, только перенести ее в другое место.Лучше всего всегда поддерживать концепцию «один интерфейс-объект, один владелец».
Если COM-сервер желает поддерживать концепцию, согласно которой два (или более) интерфейса могут ссылаться на некоторое общее внутреннее состояние сервераCOM-сервер должен объявлять контракт, предоставляя метод CreateCopyOfInstance и управлять конфликтами внутри компании.Конечно, есть примеры серверов, которые справляются с таким «разветвлением».Посмотрите на интерфейсы постоянного хранения от Microsoft.Там интерфейсы НЕ «разветвляются». Каждый интерфейс должен принадлежать одному пользователю (поток / процесс / что угодно), а «разветвление» управляется внутренне сервером с помощью методов, предоставляемыхCOM-клиенты для контроля некоторых аспектов конфликтных вопросов.Поэтому COM-серверы Microsoft должны учитывать условия гонки в рамках своих контрактов со своими клиентами.