COM多线程和DCOM学习心得160217_第二章多任务和多线程
COM多线程和DCOM学习心得160217由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“第二章多任务和多线程”。
COM多线程和DCOM 1 COM多线程模型
COM提供的线程模型共有三种:Single-Threaded Apartment(STA 单线程套间)、Multithreaded Apartment(MTA 多线程套间)和Neutral Apartment/Thread Neutral Apartment/Neutral Threaded Apartment(NA/TNA/NTA 中立线程套间,由COM+提供)。虽然它们的名字都含有套间这个词,这只是COM运行时期库(注意,不是COM规范,以下简称COM)使用套间技术来实现前面的三种线程模型,应注意套间和线程模型不是同一个概念。COM提供的套间共有三种,分别一一对应。而线程模型的存在就是线程规则的不同导致的,而所谓的线程规则就只有两个:代码是线程安全的或不安全的,即代码访问公共数据时会或不会发生访问冲突。
1.1 COM套间
套间(Apartment)是线程模型的一个实现者,就像在操作系统课程中讲到的线程只是一个数学模型,而Windows的线程、进程是它(数学模型的线程、进程)的实现者。套间只是逻辑上的一个概念,实现时只是一个结构(由COM管理)而已,记录着相关信息,如它的种类(只能是上面那三个,至少现在是),并由COM根据那个结构进行相应的处理。下面说明这三种套间的实现方式:
STA套间:一个套间如果是STA,那么那个套间有且只有一个线程和其关联,有多个对象或没有对象和其关联,就像有多个线程和一个进程关联一样,也就是说套间那个结构和某个线程及多个对象之间有关系,关系具体是什么由COM说得算,幸运的是COM正是按照上面的线程模型来定义互相之间关系的。根据上面的算法,很容易就知道只有这个线程可以访问这个套间里的对象。COM是通过在STA套间里的线程中创建一个隐藏窗口,然后外界(这个套间外的线程)对这个对象的调用都转变成对那个隐藏窗口发送消息,然后由这个隐藏窗口的消息处理函数来实际调用组件对象的方法来实现STA的规则的。之所以使用一个隐藏窗口是为了方便组件代码的编写——只需调用DispatchMeage即可将方法调用的消息和普通的消息区分开来(通过隐藏窗口的消息处理函数)。外界对这个对象的调用都将转变成对这个隐藏窗口的消息发送来实现同步。至于COM如何截获外界对对象的调用,则是利于代理对象,后面再说明。
MTA套间:这种类型的套间可以和多个线程及多个或没有对象相关联。根据上面的MTA模型,可知只有这个套间里的线程才能访问这个套间里的对象,和STA不同的只是可以多个线程同时访问对象。外界(不属于这个套间的线程)对这个套间里的对象的调用将会导致调用线程(外界线程,也就是STA线程,因为NA没有线程)挂起,然后向RPC管理的一个线程池请求一个线程(RPC线程,并已经进入了这个MTA套间)以调用那个对象的方法。对象返回后,调用线程被唤醒,继续运行。虽然可以让STA线程直接调用对象(而不用像前述的挂起等待另一个线程来调用对象),但这是必须的,因为可能会有回调问题,比如这个MTA线程又反过来回调外界线程中的组件对象(假设客户本身也是一个组件对象,这正是连接点技术),如果异步回调将可能发生错误。反过来,MTA的线程访问STA里的对象时,COM将把调用转换成对STA线程里那个隐藏窗口的一个消息发送,返回后再由COM转成结果返回给MTA的线程(如果使用标准汇集法生成标准代理对象,则发生的具体情况就如上面STA套间所述)。因此STA和MTA都是只能由它们关联的线程调用它们关联的对象。而根据上面所说,当MTA调STA或STA调MTA,都会发生线程切换,也就是说一个线程挂起而换成执行另一个线程。这是相当大的消耗(需要从内核模式向用户模式转换,再倒转好几回),而NA就是针对这个设计的。
NA套间:这种套间只和对象相关联,没有关联的线程,因此任何线程都可以直接访问里面的对象,不存在STA的还是MTA的。外界(其实就是任何线程)对这个套间里面的调用都不需要挂起等待,而是进入NA套间,直接调用对象的方法。NA套间是由COM+提供的,COM+中的每个对象都有一个环境和其相绑定,环境记录了必要的信息,并监听对对象的每一次调用,以保证当将对象的接口指针成员变量进行传递或回调时其操作的正确性(保证执行线程在正确的套间内,MTA线程就是通过将自己挂起以等待STA线程的消息处理完毕来保证的),从而避免了调用线程的挂起,因此这个代理(其实也就是环境的一部分)被称作轻量级代理(相对于STA套间和MTA套间的重量级代理——需要挂起调用线程,发生线程切换)。
1.2 套间实现规则
COM的套间机制要成功实现,必须服务器(组件)、客户和COM运行时期库三方面合力实现,其中有任何一方不按着规矩来,将不能实现套间机制的功能,不过这并不代表什么错误,套间机制不能运作并不代表程序会崩溃,只是不能和其他COM应用兼容而已。比如:对象中的属性1在设计的算法中肯定不会被两个以上的线程写入,只是会被多个线程同时读出而已,因此不用同步,可以用MTA,但对象的属性2却可能被多个线程写入,因此决定使用STA。从而在客户端,通过前面说的CoMarshalInterface和CoUnmarshalInterface将对象指针传到那个只会写入对象的属性1的线程,其实这时就可以直接将对象指针传到这个线程,而不用想上面那样麻烦(而且增加了效率),但是就破坏了COM的套间规矩了——两个线程可以访问对象,但对象在STA套间中。所以?!什么事都不会发生,因为已经准确知道这个算法不会捅娄子(线程访问冲突),即使破坏COM的规矩又怎样?!而且组件仍可以和其他客户兼容,因为不按规矩来的是客户,与组件无关。不过如果组件破坏规矩,那么它将不能和每一个客户兼容,但并不代表它和任何客户都不兼容。这里其实就是客户和组件联合起来欺骗了COM运行时期库。
STA 当一个组件是STA时,它必须同步保护全局变量和静态变量,即对全局变量和静态变量的访问应该用临界段或其他同步手段保护,因为操作全局和静态变量的代码可以被多个STA线程同时执行,所以那些代码的地方要进行保护。比如对象计数(注意,不是引用计数),代表当前组件生成的对象个数,当减为零时,组件被卸载。此变量一般被类厂对象使用,还好ATL和MFC已经帮我们实现了缺省类厂,这里一般不用担心,但自定义的全局或静态变量得自己处理。
主STA 与STA唯一的不同是这是傻瓜型的,连静态和全局变量都可以不用线程保护,因为所有不是安全访问静态和全局变量的对象都通过主线程(第一个调用CoInitialize的线程)的消息派送机制运行,因此不安全的访问都被集中到了一个线程的调用中,因而调用被序列化了,也就实现了对静态和全局变量的线程保护。至于为什么是主线程,因为进程要使用STA,则一定会创建主线程,所以一定可以创建主STA。因此主STA并不是什么第四种套间,只是一个STA套间,不过关联的是主线程而已,由于它可以被用作保护静态和全局变量而被单独提出来说明。因此一个进程内也只有一个主STA套间。2 分布式DCOM DCOM(分布式组件对象模型,分布式组件对象模式)是一系列微软的概念和程序接口,利用这个接口,客户端程序对象能够请求来自网络中另一台计算机上的服务器程序对象。DCOM基于组件对象模型(COM),COM提供了一套允许同一台计算机上的客户端和服务器之间进行通信的接口。
2.1 DCOM对象的创建
DCOM使得组件的位置对你来说完全透明,无论它是位于客户的同一进程中或是在地球的另一端。在任何情况下,客户连接组件和调用组件的方法的方式都是一样的。DCOM不仅无需改变源码,而且无需重新编译程序。一个简单的再配置动作就改变了组件组件之间相互连接的方式。DCOM的位置独立性极大地简化了将应用组件分布化的任务,使其能够达到最合适的执行效果。例如,设想某个组件必需位于某台特定的机器上或某个特定的位置,并且此应用有许多小组件,你可以通过将这些组件配置在同一个LAN上,或者同一台机器上,甚至同一个进程中来减少网络的负载。
创建COM对象可以在C OM库的基础上,通过远程调用SCM来实现。
客户调用创建函数COM库(OLE32.DLL)远程创建SCM(RPCSS.EXE)RPCSCM(RPCSS.EXE)组件创建进程和对象
图创建DCOM组件对象
2.2 DCOM的连接和并发管理
DCOM使用ORPC协议实现远程通信。连接具有可传递性,因为接口的列集数据(OR或者OBJREF)包含机器相关的信息;连接传递与创建传递含义不同,DCOM不支持创建传递, 可用连接传递间接支持创建传递,利用连接传递性可实现动态负载平衡。
服务器1①请求创建对象A客户机②pA->CreateObjectB④返回对象B⑤释放对象A⑥客户直接与对象B连接服务器3名字开放服务器③选择服务器3并创建对象B服务器2 图 DCOM连接管理
客户程序或者组件程序实现过滤器对象,然后用CoRegisterMeageFilter函数指定使用自定义的消息过滤器;否则COM使用缺省的过滤器对象。
2.3 DCOM安全性
DCOM使用了Windows NT提供的扩展的安全框架。Windows NT提供了一套稳固的内建式安全模块,它用来提供从传统的信用领域的安全模式到非集中管理模式的复杂的身份确认和鉴定机制,极大地扩展了公钥式安全机制。安全性框架的中心部分是一个用户目录,它存储着用来确认用户凭据(用户名、密码、公钥)的必要信息。大多数并非基于Windows NT平台的系统提供了相似或相同的扩展机制,我们可以使用这种机制而不用管此平台上用的是哪种安全模块。大多数DCOM的UNIX版本提供了同Windows NT平台相容的安全模块。