COM引用计数-线程安全
COM reference counting - thread safety
如果我有一个COM对象,是否需要为AddRef()和Release()方法是线程安全的-即,我必须使用我的ref计数原子操作?
是的,如果你正在使用自由线程公寓模型,使用InterlockedIncrement()和InterlockedDecrement()来处理ref count
我认为答案是否定的。它不是必需的。如果你希望你的COM对象是线程安全的,那么那些应该是线程安全的。否则它们不必是。
。如果你看这里:组件对象模型的规则,它并没有作为一个需求被提到。你也可以在《COM程序员的食谱(构建COM组件)》中看到一个没有线程安全引用计数的示例对象。
Microsoft代码片段:
ULONG COutside::AddRef (void)
{
return ++ m_cRef;
}
在实践中,大多数实现都会这样做,因为否则COM对象将不是线程安全的。如果你知道对象将只在一个线程中使用,我相信这是一个允许的优化。并不是所有的COM对象都是线程安全的,我曾经处理过一些不是的。
为了处理COM对象可能是也可能不是线程安全的事实,COM提供了创建COM对象的不同"公寓"。在单线程公寓中,只有一个线程可以访问该公寓中的对象,而在多线程公寓中,对象可以在多个线程之间共享。引用自理解和使用COM线程模型:
"虽然多线程公寓,有时称为自由线程公寓是一种简单得多的模式,他们更难以发展因为开发人员必须实现的线程同步对象,这绝对是一项不平凡的任务。"
是的。这是必须的。COM是一个简单的二进制标准,如果你使用自由线程公寓,你将获得真正的自由线程访问
这取决于你使用的线程模型和对象的类型。请参见_ATL_*_THREADED
宏的描述。这些宏影响"普通"类和工厂的AddRef()/Release()
的线程安全。
如果使用"too loose"宏,就违反了线程安全要求,程序可能会出现故障。如果你选择一个"太紧"的宏,你可能会损失一些性能,但你通常不知道你是否关心在你的配置文件。
这是如何选择正确的宏(这解释了AddRef()/Release()
是否必须是线程安全的)。
如果单个服务器的所有类都没有指定的线程模型(主STA),那么就没有机会并发访问对象或工厂,它们都可以具有非线程安全的AddRef()/Release()
,您可以通过指定_ATL_SINGLE_THREADED
宏来获得这一点。
否则,如果至少有一个类有"公寓"模型指定,你需要线程安全的AddRef()/Release()
为该对象的工厂,但仍然可以有一个非线程安全的AddRef()/Release()
在对象本身,你得到这个通过指定_ATL_APARTMENT_THREADED
宏。这个宏将使所有工厂具有线程安全的AddRef()/Release()
和所有对象非线程安全的AddRef()/Release()
。
最后,如果至少有一个类指定了"Both"或"Free"线程模型,那么您需要AddRef()/Release()
在该类和工厂中都是线程安全的,并且您必须指定_ATL_FREE_THREADED
或不指定上述任何一个-默认情况下,这个"最紧密"的宏效果将被打开。因此,使用ATL创建的COM对象的默认配置是为所有对象(包括服务对象和工厂)提供线程安全的AddRef()/Release()
。
也就是说,你并不总是需要AddRef()/Release()
是线程安全的,但你通常应该这样做,除非你确定你可以不使用它,并且不使用它可以获得性能
- 如何将元素添加到数组的线程安全函数?
- C++中的线程安全删除
- 在std::thread中,joinable()然后join()线程安全吗
- 在c++队列中使用pop和visit实现线程安全
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 全局变量 多读取器 一个写入器多线程安全?
- 共享队列的线程安全
- boost::文件系统::recursive_directory_iterator多线程安全
- 以线程安全的方式转换 C/C++ 中时区名称字符串的时区偏移量
- 线程安全运算符<<
- 如何使缓存线程安全
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 提升精神 V2 Qi 语法线程安全吗?
- asio 链对象线程安全吗?
- 线程安全队列 c++
- 提供对不同类型的数据(建议、代码审查)的线程安全访问的类
- 如何以线程安全的方式更改目录?
- 线程安全的引用计数队列C++
- 析构函数和线程安全
- 适用于大型数组的无复制线程安全环形缓冲区