天天看点

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

<a href="http://webabcd.blog.51cto.com/1787395/343999" target="_blank">[索引页]</a>

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

介绍

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

示例

1、服务

Enum.cs

using System; 

using System.Collections.Generic; 

using System.Linq; 

using System.Text; 

using System.ServiceModel; 

using System.Runtime.Serialization; 

namespace WCF.ServiceLib.ConcurrencyLock 

        /// &lt;summary&gt; 

        /// 锁 类型的枚举 

        /// &lt;/summary&gt; 

        [DataContract] 

        public enum LockType 

        { 

                /// &lt;summary&gt; 

                /// 不使用任何并发控制 

                /// &lt;/summary&gt; 

                [EnumMember] 

                None, 

                /// Mutex 

                Mutex, 

                /// Semaphore 

                Semaphore, 

                /// Monitor 

                Monitor, 

                /// Lock 

                Lock 

        } 

}

IHello.cs

        /// 演示并发控制(锁)的接口 

        [ServiceContract] 

        public interface IHello 

                /// 计数器 

                /// &lt;param name="lockType"&gt;锁的类型&lt;/param&gt; 

                [OperationContract] 

                void Counter(LockType lockType); 

                /// 获取计数器被调用的结果 

                /// &lt;returns&gt;&lt;/returns&gt; 

                string GetResult(); 

                /// 清空计数器和结果 

                void CleanResult(); 

Hello.cs

        /// &lt;remarks&gt; 

        /// ServiceBehavior - 指定服务协定实现的内部执行行为 

        /// 实例模型:单例;并发模式:多线程 

        /// 会有并发问题,通过 锁 来解决 

        /// &lt;/remarks&gt; 

        [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] 

        public class Hello : IHello 

                private int _counter; 

                private string _result; 

                private System.Threading.Mutex _mutex = new System.Threading.Mutex(); 

                // 此构造函数初始化未命名的信号量。所有使用这类信号量的实例的线程都必须具有对该实例的引用。 

                // 如果 initialCount 小于 maximumCount,则效果与当前线程调用了 WaitOne(maximumCount 减去 initialCount)次相同。如果不想为创建信号量的线程保留任何入口,请对 maximumCount 和 initialCount 使用相同的数值。 

                private System.Threading.Semaphore _semaphore = new System.Threading.Semaphore(1, 1); 

                private static readonly object objLock = new object(); 

                public void Counter(LockType lockType) 

                { 

                        switch (lockType) 

                        { 

                                case LockType.None: 

                                        ExecuteNone(); 

                                        break; 

                                case LockType.Mutex: 

                                        ExecuteMutex(); 

                                case LockType.Semaphore: 

                                        ExecuteSemaphore(); 

                                case LockType.Monitor: 

                                        ExecuteMonitor(); 

                                case LockType.Lock: 

                                        ExecuteLock(); 

                        } 

                } 

                public string GetResult() 

                        return _result; 

                public void CleanResult() 

                        _result = ""; 

                        _counter = 0; 

                /// 循环调用技术器,以模拟并发 

                /// 结果中,出现重复计数,则有并发问题,反之,则无并发问题 

                private void CircleCounter() 

                        for (int i = 0; i &lt; 10; i++) 

                                var counter = _counter; 

                                // 停20毫秒,以模拟并发 

                                System.Threading.Thread.Sleep(20); 

                                _counter = ++counter; 

                                // 保存计数结果 

                                _result += _counter + "|"; 

                private void ExecuteNone() 

                        CircleCounter(); 

                /// Mutex的实现 

                private void ExecuteMutex() 

                        try 

                                _mutex.WaitOne(); 

                                CircleCounter(); 

                        finally 

                                _mutex.ReleaseMutex(); 

                /// Semaphore的实现 

                private void ExecuteSemaphore() 

                                _semaphore.WaitOne(); 

                                _semaphore.Release(); 

                /// Monitor的实现 

                private void ExecuteMonitor() 

                                System.Threading.Monitor.Enter(this); 

                                System.Threading.Monitor.Exit(this); 

                /// Lock的实现 

                private void ExecuteLock() 

                                lock (objLock) 

                                { 

                                        CircleCounter(); 

                                } 

2、宿主

Hello.svc

&lt;%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.ConcurrencyLock.Hello" %&gt;

Web.config

&lt;?xml version="1.0"?&gt; 

&lt;configuration&gt; 

        &lt;system.serviceModel&gt; 

                &lt;behaviors&gt; 

                        &lt;serviceBehaviors&gt; 

                                &lt;behavior name="ConcurrencyLockBehavior"&gt; 

                                        &lt;!--httpGetEnabled - 指示是否发布服务元数据以便使用 HTTP/GET 请求进行检索,如果发布 WSDL,则为 true,否则为 false,默认值为 false--&gt; 

                                        &lt;serviceMetadata httpGetEnabled="true" /&gt; 

                                        &lt;serviceDebug includeExceptionDetailInFaults="true"/&gt; 

                                &lt;/behavior&gt; 

                        &lt;/serviceBehaviors&gt; 

                &lt;/behaviors&gt; 

                &lt;services&gt; 

                        &lt;!--name - 提供服务的类名--&gt; 

                        &lt;!--behaviorConfiguration - 指定相关的行为配置--&gt; 

                        &lt;service name="WCF.ServiceLib.ConcurrencyLock.Hello" behaviorConfiguration="ConcurrencyLockBehavior"&gt; 

                                &lt;!--address - 服务地址--&gt; 

                                &lt;!--binding - 通信方式--&gt; 

                                &lt;!--contract - 服务契约--&gt; 

                                &lt;endpoint address="" binding="basicHttpBinding" contract="WCF.ServiceLib.ConcurrencyLock.IHello" /&gt; 

                        &lt;/service&gt; 

                &lt;/services&gt; 

        &lt;/system.serviceModel&gt; 

&lt;/configuration&gt;

3、客户端

Hello.aspx

&lt;%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Hello.aspx.cs" 

        Inherits="ConcurrencyLock_Hello" Title="并发控制(锁)(Mutex, Semaphore, Monitor, Lock, ThreadPool, Interlocked, ReaderWriterLock)" %&gt; 

&lt;asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server"&gt; 

&lt;/asp:Content&gt; 

&lt;asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"&gt; 

        &lt;p&gt; 

                &lt;asp:Button ID="btnCleanResult" runat="server" Text="清空结果" OnClick="btnCleanResult_Click" /&gt; 

                &lt;asp:Button ID="btnHelloNone" runat="server" Text="HelloNone" OnCommand="btn_Command" 

                        CommandName="None" /&gt; 

                &lt;asp:Button ID="btnHelloMutex" runat="server" Text="HelloMutex" OnCommand="btn_Command" 

                        CommandName="Mutex" /&gt; 

                &lt;asp:Button ID="btnHelloSemaphore" runat="server" Text="HelloSemaphore" OnCommand="btn_Command" 

                        CommandName="Semaphore" /&gt; 

                &lt;asp:Button ID="btnHelloMonitor" runat="server" Text="HelloMonitor" OnCommand="btn_Command" 

                        CommandName="Monitor" /&gt; 

                &lt;asp:Button ID="btnHelloLock" runat="server" Text="HelloLock" OnCommand="btn_Command" 

                        CommandName="Lock" /&gt; 

                &lt;br /&gt; 

                &lt;ul&gt; 

                        &lt;li&gt;None:不使用并发控制(有并发问题,会出现重复的计数)&lt;/li&gt; 

                        &lt;li&gt;其他:使用相关的并发控制(无并发问题,不会出现重复的计数)&lt;/li&gt; 

                &lt;/ul&gt; 

        &lt;/p&gt; 

        &lt;div&gt; 

                &lt;asp:TextBox ID="txtResult" runat="server" TextMode="MultiLine" Style="width: 98%; 

                        height: 200px" /&gt; 

        &lt;/div&gt; 

                        &lt;li&gt;Mutex - 提供对资源的独占访问&lt;/li&gt; 

                        &lt;li&gt;Semaphore - 限制可同时访问某一资源或资源池的线程数&lt;/li&gt; 

                        &lt;li&gt;Monitor - 提供同步访问对象的机制&lt;/li&gt; 

                        &lt;li&gt;Lock - 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁&lt;/li&gt; 

                        &lt;li&gt;ThreadPool - 提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器&lt;/li&gt; 

                        &lt;li&gt;Interlocked - 为多个线程共享的变量提供原子操作&lt;/li&gt; 

                        &lt;li&gt;ReaderWriterLock - 定义支持单个写线程和多个读线程的锁&lt;/li&gt; 

&lt;/asp:Content&gt;

Hello.aspx.cs

using System.Collections; 

using System.Configuration; 

using System.Data; 

using System.Web; 

using System.Web.Security; 

using System.Web.UI; 

using System.Web.UI.HtmlControls; 

using System.Web.UI.WebControls; 

using System.Web.UI.WebControls.WebParts; 

using System.Xml.Linq; 

using System.Threading; 

public partial class ConcurrencyLock_Hello : System.Web.UI.Page 

        protected void Page_Load(object sender, EventArgs e) 

        protected void btn_Command(object sender, CommandEventArgs e) 

                // 线程1 

                var thread1 = new Thread(new ParameterizedThreadStart(Do)); 

                thread1.Start(e.CommandName); 

                // 线程2 

                var thread2 = new Thread(new ParameterizedThreadStart(Do)); 

                thread2.Start(e.CommandName); 

                for (int i = 0; i &lt; 100; i++) 

                        Thread.Sleep(100); 

                        if (thread1.ThreadState == ThreadState.Stopped &amp;&amp; thread2.ThreadState == ThreadState.Stopped) 

                                // 返回服务端的技术器的调用结果 

                                var proxy = new ConcurrencyLockSvc.HelloClient(); 

                                txtResult.Text = proxy.GetResult(); 

                                proxy.Close(); 

                                break; 

        private void Do(object commandName) 

                ConcurrencyLockSvc.LockType lockType = (ConcurrencyLockSvc.LockType)Enum.Parse(typeof(ConcurrencyLockSvc.LockType), (string)commandName); 

                // 调用服务端技术器 

                using (var proxy = new ConcurrencyLockSvc.HelloClient()) 

                        proxy.Counter(lockType); 

        protected void btnCleanResult_Click(object sender, EventArgs e) 

                // 清空计数器和结果 

                        proxy.CleanResult(); 

                txtResult.Text = ""; 

                &lt;client&gt; 

                        &lt;!--address - 服务地址--&gt; 

                        &lt;!--binding - 通信方式--&gt; 

                        &lt;!--contract - 服务契约--&gt; 

                        &lt;endpoint address="http://localhost:3502/ServiceHost/ConcurrencyLock/Hello.svc" binding="basicHttpBinding" contract="ConcurrencyLockSvc.IHello" /&gt; 

                &lt;/client&gt; 

运行结果:

单击"HelloNone"按钮:不使用并发控制(有并发问题,会出现重复的计数)

单击"HelloMutex", "HelloSemaphore", "HelloMonitor", "HelloLock"按钮:使用相应的并发控制(无并发问题,不会出现重复的计数)

OK

<a href="http://down.51cto.com/data/100781" target="_blank">[源码下载]</a>

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

继续阅读