化零为整WCF(13) - 并发控制(锁)(Mutex, Semaphore, Monitor, Lock, ThreadPool, Interlocked

简介:
[索引页]
[源码下载] 


化零为整WCF(13) - 并发控制(锁)(Mutex, Semaphore, Monitor, Lock, ThreadPool, Interlocked, ReaderWriterLock)


作者: webabcd


介绍
WCF(Windows Communication Foundation) - 并发控制:以ConcurrencyMode.Multiple并发模式及InstanceContextMode.Single实例模型为例(此时有并发问题),介绍如何做并发控制,即各种锁的使用(Mutex, Semaphore, Monitor, Lock, ThreadPool, Interlocked, ReaderWriterLock)


示例
1、服务
Enum.cs
InBlock.gif using System; 
InBlock.gif using System.Collections.Generic; 
InBlock.gif using System.Linq; 
InBlock.gif using System.Text; 
InBlock.gif 
InBlock.gif using System.ServiceModel; 
InBlock.gif using System.Runtime.Serialization; 
InBlock.gif 
InBlock.gif namespace WCF.ServiceLib.ConcurrencyLock 
InBlock.gif
InBlock.gif         /// <summary> 
InBlock.gif         /// 锁 类型的枚举 
InBlock.gif         /// </summary> 
InBlock.gif        [DataContract] 
InBlock.gif         public  enum LockType 
InBlock.gif        { 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 不使用任何并发控制 
InBlock.gif                 /// </summary> 
InBlock.gif                [EnumMember] 
InBlock.gif                None, 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// Mutex 
InBlock.gif                 /// </summary> 
InBlock.gif                [EnumMember] 
InBlock.gif                Mutex, 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// Semaphore 
InBlock.gif                 /// </summary> 
InBlock.gif                [EnumMember] 
InBlock.gif                Semaphore, 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// Monitor 
InBlock.gif                 /// </summary> 
InBlock.gif                [EnumMember] 
InBlock.gif                Monitor, 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// Lock 
InBlock.gif                 /// </summary> 
InBlock.gif                [EnumMember] 
InBlock.gif                Lock 
InBlock.gif        } 
InBlock.gif}
 
IHello.cs
InBlock.gif using System; 
InBlock.gif using System.Collections.Generic; 
InBlock.gif using System.Linq; 
InBlock.gif using System.Text; 
InBlock.gif 
InBlock.gif using System.ServiceModel; 
InBlock.gif 
InBlock.gif namespace WCF.ServiceLib.ConcurrencyLock 
InBlock.gif
InBlock.gif         /// <summary> 
InBlock.gif         /// 演示并发控制(锁)的接口 
InBlock.gif         /// </summary> 
InBlock.gif        [ServiceContract] 
InBlock.gif         public  interface IHello 
InBlock.gif        { 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 计数器 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="lockType">锁的类型</param> 
InBlock.gif                [OperationContract] 
InBlock.gif                 void Counter(LockType lockType); 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 获取计数器被调用的结果 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                [OperationContract] 
InBlock.gif                 string GetResult(); 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 清空计数器和结果 
InBlock.gif                 /// </summary> 
InBlock.gif                [OperationContract] 
InBlock.gif                 void CleanResult(); 
InBlock.gif        } 
InBlock.gif}
 
Hello.cs
InBlock.gif using System; 
InBlock.gif using System.Collections.Generic; 
InBlock.gif using System.Linq; 
InBlock.gif using System.Text; 
InBlock.gif 
InBlock.gif using System.ServiceModel; 
InBlock.gif 
InBlock.gif namespace WCF.ServiceLib.ConcurrencyLock 
InBlock.gif
InBlock.gif         /// <summary> 
InBlock.gif         /// 演示并发控制(锁)的接口 
InBlock.gif         /// </summary> 
InBlock.gif         /// <remarks> 
InBlock.gif        /// ServiceBehavior - 指定服务协定实现的内部执行行为 
InBlock.gif        /// 实例模型:单例;并发模式:多线程 
InBlock.gif        /// 会有并发问题,通过 锁 来解决 
InBlock.gif        /// </remarks> 

InBlock.gif        [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] 
InBlock.gif         public  class Hello : IHello 
InBlock.gif        { 
InBlock.gif                 private  int _counter; 
InBlock.gif                 private  string _result; 
InBlock.gif 
InBlock.gif                 private System.Threading.Mutex _mutex =  new System.Threading.Mutex(); 
InBlock.gif 
InBlock.gif                 // 此构造函数初始化未命名的信号量。所有使用这类信号量的实例的线程都必须具有对该实例的引用。 
InBlock.gif                 // 如果 initialCount 小于 maximumCount,则效果与当前线程调用了 WaitOne(maximumCount 减去 initialCount)次相同。如果不想为创建信号量的线程保留任何入口,请对 maximumCount 和 initialCount 使用相同的数值。 
InBlock.gif                 private System.Threading.Semaphore _semaphore =  new System.Threading.Semaphore(1, 1); 
InBlock.gif 
InBlock.gif                 private  static  readonly  object objLock =  new  object(); 
InBlock.gif 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 计数器 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public  void Counter(LockType lockType) 
InBlock.gif                { 
InBlock.gif                         switch (lockType) 
InBlock.gif                        { 
InBlock.gif                                 case LockType.None: 
InBlock.gif                                        ExecuteNone(); 
InBlock.gif                                         break
InBlock.gif                                 case LockType.Mutex: 
InBlock.gif                                        ExecuteMutex(); 
InBlock.gif                                         break
InBlock.gif                                 case LockType.Semaphore: 
InBlock.gif                                        ExecuteSemaphore(); 
InBlock.gif                                         break
InBlock.gif                                 case LockType.Monitor: 
InBlock.gif                                        ExecuteMonitor(); 
InBlock.gif                                         break
InBlock.gif                                 case LockType.Lock: 
InBlock.gif                                        ExecuteLock(); 
InBlock.gif                                         break
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 获取计数器被调用的结果 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public  string GetResult() 
InBlock.gif                { 
InBlock.gif                         return _result; 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 清空计数器和结果 
InBlock.gif                 /// </summary> 
InBlock.gif                 public  void CleanResult() 
InBlock.gif                { 
InBlock.gif                        _result = ""; 
InBlock.gif                        _counter = 0; 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 循环调用技术器,以模拟并发 
InBlock.gif                 /// 结果中,出现重复计数,则有并发问题,反之,则无并发问题 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void CircleCounter() 
InBlock.gif                { 
InBlock.gif                         for ( int i = 0; i < 10; i++) 
InBlock.gif                        { 
InBlock.gif                                var counter = _counter; 
InBlock.gif 
InBlock.gif                                 // 停20毫秒,以模拟并发 
InBlock.gif                                System.Threading.Thread.Sleep(20); 
InBlock.gif 
InBlock.gif                                _counter = ++counter; 
InBlock.gif 
InBlock.gif                                 // 保存计数结果 
InBlock.gif                                _result += _counter +  "|"
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 不使用任何并发控制 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void ExecuteNone() 
InBlock.gif                { 
InBlock.gif                        CircleCounter(); 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// Mutex的实现 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void ExecuteMutex() 
InBlock.gif                { 
InBlock.gif                         try 
InBlock.gif                        { 
InBlock.gif                                _mutex.WaitOne(); 
InBlock.gif 
InBlock.gif                                CircleCounter(); 
InBlock.gif                        } 
InBlock.gif                         finally 
InBlock.gif                        { 
InBlock.gif                                _mutex.ReleaseMutex(); 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// Semaphore的实现 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void ExecuteSemaphore() 
InBlock.gif                { 
InBlock.gif                         try 
InBlock.gif                        { 
InBlock.gif                                _semaphore.WaitOne(); 
InBlock.gif 
InBlock.gif                                CircleCounter(); 
InBlock.gif                        } 
InBlock.gif                         finally 
InBlock.gif                        { 
InBlock.gif                                _semaphore.Release(); 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// Monitor的实现 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void ExecuteMonitor() 
InBlock.gif                { 
InBlock.gif                         try 
InBlock.gif                        { 
InBlock.gif                                System.Threading.Monitor.Enter( this); 
InBlock.gif 
InBlock.gif                                CircleCounter(); 
InBlock.gif                        } 
InBlock.gif                         finally 
InBlock.gif                        { 
InBlock.gif                                System.Threading.Monitor.Exit( this); 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// Lock的实现 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void ExecuteLock() 
InBlock.gif                { 
InBlock.gif                         try 
InBlock.gif                        { 
InBlock.gif                                 lock (objLock) 
InBlock.gif                                { 
InBlock.gif                                        CircleCounter(); 
InBlock.gif                                } 
InBlock.gif                        } 
InBlock.gif                         finally 
InBlock.gif                        { 
InBlock.gif 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif        } 
InBlock.gif}
 
 
2、宿主
Hello.svc
<%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.ConcurrencyLock.Hello" %>
 

Web.config
<?xml version="1.0"?> 
<configuration> 
        <system.serviceModel> 
                <behaviors> 
                        <serviceBehaviors> 
                                <behavior name="ConcurrencyLockBehavior"> 
                                        <!--httpGetEnabled - 指示是否发布服务元数据以便使用 HTTP/GET 请求进行检索,如果发布 WSDL,则为 true,否则为 false,默认值为 false--> 
                                        <serviceMetadata httpGetEnabled="true" /> 
                                        <serviceDebug includeExceptionDetailInFaults="true"/> 
                                </behavior> 
                        </serviceBehaviors> 
                </behaviors> 
                <services> 
                        <!--name - 提供服务的类名--> 
                        <!--behaviorConfiguration - 指定相关的行为配置--> 
                        <service name="WCF.ServiceLib.ConcurrencyLock.Hello" behaviorConfiguration="ConcurrencyLockBehavior"> 
                                <!--address - 服务地址--> 
                                <!--binding - 通信方式--> 
                                <!--contract - 服务契约--> 
                                <endpoint address="" binding="basicHttpBinding" contract="WCF.ServiceLib.ConcurrencyLock.IHello" /> 
                        </service> 
                </services> 
        </system.serviceModel> 
</configuration>
 
 

3、客户端
Hello.aspx
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Hello.aspx.cs" 
        Inherits="ConcurrencyLock_Hello" Title="并发控制(锁)(Mutex, Semaphore, Monitor, Lock, ThreadPool, Interlocked, ReaderWriterLock)" %> 

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server"> 
</asp:Content> 
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"> 
        <p> 
                <asp:Button ID="btnCleanResult" runat="server" Text="清空结果" OnClick="btnCleanResult_Click" /> 
                  
                <asp:Button ID="btnHelloNone" runat="server" Text="HelloNone" OnCommand="btn_Command" 
                        CommandName="None" /> 
                  
                <asp:Button ID="btnHelloMutex" runat="server" Text="HelloMutex" OnCommand="btn_Command" 
                        CommandName="Mutex" /> 
                  
                <asp:Button ID="btnHelloSemaphore" runat="server" Text="HelloSemaphore" OnCommand="btn_Command" 
                        CommandName="Semaphore" /> 
                  
                <asp:Button ID="btnHelloMonitor" runat="server" Text="HelloMonitor" OnCommand="btn_Command" 
                        CommandName="Monitor" /> 
                  
                <asp:Button ID="btnHelloLock" runat="server" Text="HelloLock" OnCommand="btn_Command" 
                        CommandName="Lock" /> 
                <br /> 
                <ul> 
                        <li>None:不使用并发控制(有并发问题,会出现重复的计数)</li> 
                        <li>其他:使用相关的并发控制(无并发问题,不会出现重复的计数)</li> 
                </ul> 
        </p> 
        <div> 
                <asp:TextBox ID="txtResult" runat="server" TextMode="MultiLine" Style="width: 98%; 
                        height: 200px" /> 
        </div> 
        <div> 
                <ul> 
                        <li>Mutex - 提供对资源的独占访问</li> 
                        <li>Semaphore - 限制可同时访问某一资源或资源池的线程数</li> 
                        <li>Monitor - 提供同步访问对象的机制</li> 
                        <li>Lock - 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁</li> 
                        <li>ThreadPool - 提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器</li> 
                        <li>Interlocked - 为多个线程共享的变量提供原子操作</li> 
                        <li>ReaderWriterLock - 定义支持单个写线程和多个读线程的锁</li> 
                </ul> 
        </div> 
</asp:Content>
 
Hello.aspx.cs
InBlock.gif using System; 
InBlock.gif using System.Collections; 
InBlock.gif using System.Configuration; 
InBlock.gif using System.Data; 
InBlock.gif using System.Linq; 
InBlock.gif using System.Web; 
InBlock.gif using System.Web.Security; 
InBlock.gif using System.Web.UI; 
InBlock.gif using System.Web.UI.HtmlControls; 
InBlock.gif using System.Web.UI.WebControls; 
InBlock.gif using System.Web.UI.WebControls.WebParts; 
InBlock.gif using System.Xml.Linq; 
InBlock.gif 
InBlock.gif using System.Threading; 
InBlock.gif 
InBlock.gif public partial  class ConcurrencyLock_Hello : System.Web.UI.Page 
InBlock.gif
InBlock.gif         protected  void Page_Load( object sender, EventArgs e) 
InBlock.gif        { 
InBlock.gif 
InBlock.gif        } 
InBlock.gif 
InBlock.gif         protected  void btn_Command( object sender, CommandEventArgs e) 
InBlock.gif        { 
InBlock.gif                 // 线程1 
InBlock.gif                var thread1 =  new Thread( new ParameterizedThreadStart(Do)); 
InBlock.gif                thread1.Start(e.CommandName); 
InBlock.gif 
InBlock.gif                 // 线程2 
InBlock.gif                var thread2 =  new Thread( new ParameterizedThreadStart(Do)); 
InBlock.gif                thread2.Start(e.CommandName); 
InBlock.gif 
InBlock.gif                 for ( int i = 0; i < 100; i++) 
InBlock.gif                { 
InBlock.gif                        Thread.Sleep(100); 
InBlock.gif 
InBlock.gif                         if (thread1.ThreadState == ThreadState.Stopped && thread2.ThreadState == ThreadState.Stopped) 
InBlock.gif                        { 
InBlock.gif                                 // 返回服务端的技术器的调用结果 
InBlock.gif                                var proxy =  new ConcurrencyLockSvc.HelloClient(); 
InBlock.gif 
InBlock.gif                                txtResult.Text = proxy.GetResult(); 
InBlock.gif 
InBlock.gif                                proxy.Close(); 
InBlock.gif 
InBlock.gif                                 break
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif        } 
InBlock.gif 
InBlock.gif         private  void Do( object commandName) 
InBlock.gif        { 
InBlock.gif                ConcurrencyLockSvc.LockType lockType = (ConcurrencyLockSvc.LockType)Enum.Parse( typeof(ConcurrencyLockSvc.LockType), ( string)commandName); 
InBlock.gif 
InBlock.gif                 // 调用服务端技术器 
InBlock.gif                 using (var proxy =  new ConcurrencyLockSvc.HelloClient()) 
InBlock.gif                { 
InBlock.gif                        proxy.Counter(lockType); 
InBlock.gif                } 
InBlock.gif        } 
InBlock.gif 
InBlock.gif         protected  void btnCleanResult_Click( object sender, EventArgs e) 
InBlock.gif        { 
InBlock.gif                 // 清空计数器和结果 
InBlock.gif                 using (var proxy =  new ConcurrencyLockSvc.HelloClient()) 
InBlock.gif                { 
InBlock.gif                        proxy.CleanResult(); 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                txtResult.Text = ""; 
InBlock.gif        } 
InBlock.gif}
 
Web.config
<?xml version="1.0"?> 
<configuration> 
        <system.serviceModel> 
                <client> 
                        <!--address - 服务地址--> 
                        <!--binding - 通信方式--> 
                        <!--contract - 服务契约--> 
                        <endpoint address="http://localhost:3502/ServiceHost/ConcurrencyLock/Hello.svc" binding="basicHttpBinding" contract="ConcurrencyLockSvc.IHello" /> 
                </client> 
        </system.serviceModel> 
</configuration>
 
 
运行结果:
单击"HelloNone"按钮:不使用并发控制(有并发问题,会出现重复的计数)
单击"HelloMutex", "HelloSemaphore", "HelloMonitor", "HelloLock"按钮:使用相应的并发控制(无并发问题,不会出现重复的计数)


OK
[源码下载]



     本文转自webabcd 51CTO博客,原文链接: http://blog.51cto.com/webabcd/344157 ,如需转载请自行联系原作者

相关文章
|
9月前
|
前端开发
WCF更新服务引用报错的原因之一
WCF更新服务引用报错的原因之一
|
8月前
|
C# 数据安全/隐私保护
c#如何创建WCF服务到发布(SqlServer版已经验证)
c#如何创建WCF服务到发布(SqlServer版已经验证)
38 0
|
8月前
|
安全 数据库连接 数据库
WCF服务创建到发布(SqlServer版)
在本示例开始之前,让我们先来了解一下什么是wcf? wcf有哪些特点? wcf是一个面向服务编程的综合分层架构。该架构的项层为服务模型层。 使用户用最少的时间和精力建立自己的软件产品和外界通信的模型。它使得开发者能够建立一个跨平台的安全、可信赖、事务性的解决方案。且能与已有系统兼容写作。 简单概括就是:一组数据通信的应用程序开发接口。
57 0