• 并发中的同步WCF并发体系的同步机制实现


    在《WCF 并发的本质》中,我们谈到了WCF提供的三种不同的并发模式,使开发者可以根据具体的情况选择不同的并发处理的策略。对于这三种并发模式,Multiple采用的并行的执行方式,而Single和Reentrant则是采用串行的执行方式。串行执行即同步执行,在WCF并发框架体系中,这样的同步机制是如何实现的呢?

    一、Concurrency.Single模式下的同步实现

    实际上,WCF并发框架体系下针对Concurrency.Single模式的实现非常简单,其本质就是对InstanceContext进行加锁。如果采用反编译工具查看InstanceContext的定义,你会发现InstanceContext类中定义了一个类型为System.Object名为ThisLock的内部属性,而该属性实际上就是对基类CommunicationObject同名属性的引用,相关代码入下所示。WCF就是通过对InstanceContext的ThisLock进行加锁,确保了对InstanceContext的同步访问。

       1: public sealed class InstanceContext : CommunicationObject, IExtensibleObject<InstanceContext>
       2: {
       3:     //其它成员
       4:     internal object ThisLock
       5:     {
       6:         get
       7:         {
       8:             return base.ThisLock;
       9:         }
      10:     }
      11: }
      12: public abstract class CommunicationObject : ICommunicationObject
      13: {
      14:     //其它成员
      15:     protected object ThisLock { get; }
      16: }

    具体来讲,WCF服务端运行时在处理服务调用消息请求之后,利用实例上下文提供者(InstanceContextProvider)创建新的或者获取现有的InstanceContext。然后,WCF会将请求消息分发给该InstanceContext对消息进行进一步处理。在处理操作执行之前,如果发现相应的服务采用的并发模式是ConcurrencyMode.Single,WCF运行时会试图获取InstanceContext的ThisLock上的锁,或者说后续的操作进行再对InstanceContext的ThisLock锁定的情况下执行的。这样就保证了单一的InstanceContext对象在ConcurrencyMode.Single并发模式下永远是以同步的方式被调用的。

    二、Concurrency.Reentrant模式下的同步实现

    在ConcurrencyMode.Single并发模式下,从请求被WCF服务端运行时分发给相应的InstanceContext到请求处理完成的整个过程中,InstanceContext被锁定。如果在服务操作执行过程中涉及到对客户端的回调,并且回调操作采用请求/回复消息交换模式,当被WCF服务端运行时接收到从客户端返回的回复消息后,会将请求消息再次分发给相同的InstanceContext。运行时分发回调回复消息与普通服务调用请求消息采用相同的机制,同样需要在对InstanceContext成功锁定的情况下进行。很明显,这样产生了死锁(Deadlock)。

    所以,如果在服务操作执行过程中需要对客户端实施回调,要么将采用单向(One-way)的方式进行回调,要么将服务的并发模式设置成ConcurrencyMode.Reentrant或者ConcurrencyMode.Multiple。否则,如图1所示的InvalidOperationException异常会在进行回调操作的时候抛出。从异常消息我们可以看出,VS的汉化真的不敢恭维,如果要正常理解异常消息的含义,你需要知道这里的“邮件”、“可重输入”和“多个”是依次对“Message”、“Reentrant”和“Multiple”的翻译。

    image

    图1 在Single模式执行回调导致的异常

    如果我们真的需要在服务操作过程中实施基于请求/回复模式的回调,毫无疑问采用Concurrency.Multiple并发模式可以解决死锁的问题,因为Concurrency.Multiple模式根本就是存在对InstanceContext加锁的问题。那么,在Concurrency.Reentrant模式下,WCF并发框架体系又是如何解决这个问题的呢?

    Reentrant,翻译成汉语就是“重入”(VS将其翻译成“重输入”简直莫名其妙),意思是服务操作过程中完成了对外调用(Call Out)还能重新回到相应的位置继续执行。同Concurrency.Single模式一样,WCF运行时将调用请求消息分发给相应的InstanceContext之前,会先对其加锁。但是,在开始实施回调的之前,对InstanceContext的锁定会被解除,当回调返回后再对其加锁。

    对于Concurrency.Reentrant有一点需要特别说明,当服务端进行回调时,由于加载InstanceContext上的锁会被释放,意味着其它服务请求会被分发给该InstanceContext。当回调返回的时候,如果InstanceContext正被用于才处理在进行回调过程抵达的请求,虽然自己是先来者,依然会等待,因为重入后的InstanceContext被锁定。如果等待的时间超过设定的超时时限,客户端会抛出TimeoutException异常。

    由于WCF的并发是针对某个封装了服务实例的InstanceContext而言的,所以在不同的实例上下文模式下,会表现出不同的并发行为。在下一篇文章中,我将从具体的实例上下文模式的角度来剖析WCF的并发,敬请期待。

    作者:Artech
    出处:http://artech.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    解决显示器闪屏的问题
    装完系统后由于分辨率问题不能进入系统怎么办?怎么能不进入系统设置分表率?
    如何设置win7任务栏的计算机快速启动
    【转载】Oracle层次查询和分析函数
    【原创】birt 报表工具 不能运行 不能预览问题
    【转】最牛B的编码套路
    Windows下python环境配置
    python:numpy 下载
    TEX(LaTEX)输出PDF设置US LETTER或者LETTERPAPER办法
    Adobe Illustrator Cs6【AI cs6】中文破解版安装图文教程、破解注册方法
  • 原文地址:https://www.cnblogs.com/artech/p/1691098.html
Copyright © 2020-2023  润新知