COM+线程模型与活动同步机制解析
立即解锁
发布时间: 2025-08-20 01:59:31 阅读量: 1 订阅数: 3 


COM+编程实战:使用Visual C++和ATL构建企业级应用
### COM+ 线程模型与活动同步机制解析
#### 1. 线程安全与公寓模型概述
在不同的应用程序中,线程安全代码的范围差异很大。有些遗留应用程序完全不具备线程安全性,而精心设计的应用程序则能巧妙运用线程同步原语。还有一些应用程序存在特殊的线程约束,例如依赖线程本地存储(TLS)或使用用户界面原语。
为了让应用程序在不重新架构自身同步策略的情况下使用其他应用程序的组件,COM 将对象的并发约束视为一种运行时要求。组件开发者需要决定线程策略,也就是正式所说的线程模型。
COM+ 引入了“公寓(Apartment)”的概念,它是一组具有相同并发要求的上下文的抽象集合。一个进程可以包含一个或多个公寓,每个公寓又包含一个或多个上下文。需要注意的是,一个上下文只能存在于一个公寓中,不同公寓不会共享相同的上下文。如果要将对象引用从一个公寓传递到另一个公寓,实际上就是从一个上下文传递到另一个上下文,这种情况下通常需要进行封送处理。
线程可以通过调用 COM API `CoInitializeEx` 进入一个公寓,其原型如下:
```cpp
WINOLEAPI CoInitializeEx(/*IN*/ LPVOID pvReserved,
/*IN*/ DWORD dwCoInit);
```
第一个参数保留供未来使用,第二个参数指定线程要进入的公寓类型。线程进入一个公寓后,必须先离开当前公寓才能进入另一个公寓。离开当前公寓可以调用 `CoUninitialize`,其原型为:
```cpp
void CoUninitialize();
```
为了正确清理资源,每次成功调用 `CoInitializeEx` 后都应该调用一次 `CoUninitialize`。
COM+ 定义了三种类型的公寓,对象可以驻留在其中:
1. **单线程公寓(Single-threaded apartments,STA)**
2. **多线程公寓(Multithreaded apartments,MTA)**
3. **线程中立公寓(Thread-neutral apartments,TNA)**
#### 2. 不同类型公寓详细解析
##### 2.1 单线程公寓(STA)
单线程公寓顾名思义,在 STA 中只有一个特定的线程可以执行。所有驻留在 STA 中的对象都不会被并发访问。由于这种线程关联性,STA 适用于以下几种情况:
- 使用 TLS 作为方法调用之间的中间存储的对象。
- 成员数据没有任何保护(同步支持),需要避免共享数据冲突的对象。
- 处理用户界面的对象。
当线程调用 `CoInitializeEx` 并传递 `COINIT_APARTMENTTHREADED` 标志时,COM+ 会创建一个新的 STA 并将其与该线程关联。后续在这个新 STA 中创建的所有对象都只会在这个特定线程上接收调用。COM 还提供了简化版的 `CoInitializeEx`,即 `CoInitialize`,开发者可以使用它进入 STA,其原型如下:
```cpp
WINOLEAPI CoInitialize(/*IN*/ LPVOID pvReserved);
```
进程中每个调用 `CoInitialize`(或使用 `COINIT_APARTMENTTHREADED` 标志调用 `CoInitializeEx`)的线程都会获得一个新的 STA,因此一个进程中可能包含多个 STA。当线程调用 `CoUninitialize` 时,对应的 STA 会被销毁。
##### 2.2 多线程公寓(MTA)
在 MTA 中,多个线程可以并发执行。当线程调用 `CoInitializeEx` 并传递 `COINIT_MULTITHREADED` 值时,如果进程中还没有 MTA,COM 会为该进程创建一个 MTA。后续所有传递 `COINIT_MULTITHREADED` 调用 `CoInitializeEx` 的线程都会使用同一个 MTA,因此一个进程最多只能有一个 MTA。
在 MTA 中创建的任何对象都可以从进程中的任何 MTA 线程接收方法调用。COM 不会对对象的方法调用进行序列化,因此对象需要实现自己的同步逻辑来保护成员和全局数据。此外,由于任何 MTA 线程都可能调用对象的方法,所以对象不能存储线程特定的状态(例如使用 TLS)。虽然这种方式可以让开发者精细调整同步机制,提高性能,但也增加了代码的复杂性。当最后一个使用 MTA 的线程离开(调用 `CoUninitialize`)时,该公寓会被销毁。
##### 2.3 线程中立公寓(TNA)
由于不同公寓不共享相同的上下文,跨公寓的方法调用通常意味着跨上下文调用,这可能需要进行线程切换,而线程切换是一种开销较大的操作。线程中立公寓(TNA)可以解决这个性能问题。在 TNA 中,客户端始终会收到一个轻量级代理,当对该代理进行方法调用时,COM+ 会切换到对象的上下文而无需进行线程切换。
与 STA 和 MTA 不同,线程不能进入或离开 TNA,只有对象
0
0
复制全文
相关推荐










