COM(C++)Interlock API是否足以支持AddRef和Release中的Thread Saftey?

irs*_*sis 5 c++ windows com mapi winapi

我知道在COM对象的AddRef和Release方法内部使用了互锁API来增加/减少引用计数线程的安全性.但我试图理解这里是使用Interlock API还是我们需要某种其他同步对象,例如Mutex.到目前为止,我见过的所有示例代码都只使用了Interlock API.

场景 - 假设我已经实现了消息对象的AddRef和Release方法,如下所示.假设线程A访问消息对象,因此m_lRef count为1.一旦完成消息对象使用线程A调用Release方法

内部释放方法 - 第9行 - m_lRef = 1第10行 - m_lRef = 0,lRef = 0

线程A在第10行暂停,另一个线程B访问相同的消息,因此它调用AddRef方法,该方法将第3行的m_lRef值设置为1.现在,线程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. }
Run Code Online (Sandbox Code Playgroud)

参考计数规则

Rom*_* R. 7

这里的逻辑出错了:

m_lRef = 0

线程A在第10行暂停,另一个线程B访问相同的消息,因此它调用AddRef方法,该方法将第3行的m_lRef值设置为1.现在线程B被暂停,线程A恢复 -

如果线程B持有对该对象的有效COM引用,则单独的线程A不能合法地将计数器减少为零.线程B仍然保留一些东西,所以当线程A释放它拥有的所有内容时,引用计数器应至少为一个...

如果线程B仅执行其第一个增量,那么无论如何它应该从某处获得接口指针,这假设一个未完成的引用.如果有什么东西在没有强引用的情况下传递指针那么它就是调用者问题,而不是计数问题.

总而言之,Interlocked API非常有效且足以用于引用计数.