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


    [索引页]
    [源码下载]


    化零为整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
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    using System.ServiceModel;
    using System.Runtime.Serialization;

    namespace WCF.ServiceLib.ConcurrencyLock
    {
        
    /// <summary>
        
    /// 锁 类型的枚举
        
    /// </summary>

        [DataContract]
        
    public enum LockType
        
    {
            
    /// <summary>
            
    /// 不使用任何并发控制
            
    /// </summary>

            [EnumMember]
            None,
            
    /// <summary>
            
    /// Mutex
            
    /// </summary>

            [EnumMember]
            Mutex,
            
    /// <summary>
            
    /// Semaphore
            
    /// </summary>

            [EnumMember]
            Semaphore,
            
    /// <summary>
            
    /// Monitor
            
    /// </summary>

            [EnumMember]
            Monitor,
            
    /// <summary>
            
    /// Lock
            
    /// </summary>

            [EnumMember]
            Lock
        }

    }


    IHello.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    using System.ServiceModel;

    namespace WCF.ServiceLib.ConcurrencyLock
    {
        
    /// <summary>
        
    /// 演示并发控制(锁)的接口
        
    /// </summary>

        [ServiceContract]
        
    public interface IHello
        
    {
            
    /// <summary>
            
    /// 计数器
            
    /// </summary>
            
    /// <param name="lockType">锁的类型</param>

            [OperationContract]
            
    void Counter(LockType lockType);

            
    /// <summary>
            
    /// 获取计数器被调用的结果
            
    /// </summary>
            
    /// <returns></returns>

            [OperationContract]
            
    string GetResult();

            
    /// <summary>
            
    /// 清空计数器和结果
            
    /// </summary>

            [OperationContract]
            
    void CleanResult();
        }

    }


    Hello.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    using System.ServiceModel;

    namespace WCF.ServiceLib.ConcurrencyLock
    {
        
    /// <summary>
        
    /// 演示并发控制(锁)的接口
        
    /// </summary>
        
    /// <remarks>
        
    /// ServiceBehavior - 指定服务协定实现的内部执行行为
        
    /// 实例模型:单例;并发模式:多线程
        
    /// 会有并发问题,通过 锁 来解决
        
    /// </remarks>

        [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(11);

            
    private static readonly object objLock = new object();


            
    /// <summary>
            
    /// 计数器
            
    /// </summary>
            
    /// <returns></returns>

            public void Counter(LockType lockType)
            
    {
                
    switch (lockType)
                
    {
                    
    case LockType.None:
                        ExecuteNone();
                        
    break;
                    
    case LockType.Mutex:
                        ExecuteMutex();
                        
    break;
                    
    case LockType.Semaphore:
                        ExecuteSemaphore();
                        
    break;
                    
    case LockType.Monitor:
                        ExecuteMonitor();
                        
    break;
                    
    case LockType.Lock:
                        ExecuteLock();
                        
    break;
                }

            }


            
    /// <summary>
            
    /// 获取计数器被调用的结果
            
    /// </summary>
            
    /// <returns></returns>

            public string GetResult()
            
    {
                
    return _result;
            }


            
    /// <summary>
            
    /// 清空计数器和结果
            
    /// </summary>

            public void CleanResult()
            
    {
                _result 
    = "";
                _counter 
    = 0;
            }


            
    /// <summary>
            
    /// 循环调用技术器,以模拟并发
            
    /// 结果中,出现重复计数,则有并发问题,反之,则无并发问题
            
    /// </summary>

            private void CircleCounter()
            
    {
                
    for (int i = 0; i < 10; i++)
                
    {
                    var counter 
    = _counter;

                    
    // 停20毫秒,以模拟并发
                    System.Threading.Thread.Sleep(20);

                    _counter 
    = ++counter;

                    
    // 保存计数结果
                    _result += _counter + "|";
                }

            }


            
    /// <summary>
            
    /// 不使用任何并发控制
            
    /// </summary>

            private void ExecuteNone()
            
    {
                CircleCounter();
            }


            
    /// <summary>
            
    /// Mutex的实现
            
    /// </summary>

            private void ExecuteMutex()
            
    {
                
    try
                
    {
                    _mutex.WaitOne();

                    CircleCounter();
                }

                
    finally
                
    {
                    _mutex.ReleaseMutex();
                }

            }


            
    /// <summary>
            
    /// Semaphore的实现
            
    /// </summary>

            private void ExecuteSemaphore()
            
    {
                
    try
                
    {
                    _semaphore.WaitOne();

                    CircleCounter();
                }

                
    finally
                
    {
                    _semaphore.Release();
                }

            }


            
    /// <summary>
            
    /// Monitor的实现
            
    /// </summary>

            private void ExecuteMonitor()
            
    {
                
    try
                
    {
                    System.Threading.Monitor.Enter(
    this);

                    CircleCounter();
                }

                
    finally
                
    {
                    System.Threading.Monitor.Exit(
    this);
                }

            }


            
    /// <summary>
            
    /// Lock的实现
            
    /// </summary>

            private void ExecuteLock()
            
    {
                
    try
                
    {
                    
    lock (objLock)
                    
    {
                        CircleCounter();
                    }

                }

                
    finally
                
    {

                }

            }

        }

    }



    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" />
            
    &nbsp;
            
    <asp:Button ID="btnHelloNone" runat="server" Text="HelloNone" OnCommand="btn_Command"
                CommandName
    ="None" />
            
    &nbsp;
            
    <asp:Button ID="btnHelloMutex" runat="server" Text="HelloMutex" OnCommand="btn_Command"
                CommandName
    ="Mutex" />
            
    &nbsp;
            
    <asp:Button ID="btnHelloSemaphore" runat="server" Text="HelloSemaphore" OnCommand="btn_Command"
                CommandName
    ="Semaphore" />
            
    &nbsp;
            
    <asp:Button ID="btnHelloMonitor" runat="server" Text="HelloMonitor" OnCommand="btn_Command"
                CommandName
    ="Monitor" />
            
    &nbsp;
            
    <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=" 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
    using System;
    using System.Collections;
    using System.Configuration;
    using System.Data;
    using System.Linq;
    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 < 100; i++)
            
    {
                Thread.Sleep(
    100);

                
    if (thread1.ThreadState == ThreadState.Stopped && 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)
        
    {
            
    // 清空计数器和结果
            using (var proxy = new ConcurrencyLockSvc.HelloClient())
            
    {
                proxy.CleanResult();
            }


            txtResult.Text 
    = "";
        }

    }


    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
    [源码下载]
  • 相关阅读:
    面试题9:斐波那契数列
    面试题5:从尾到头打印链表
    面试题4:替换空格
    AOP
    (转)父类与子类之间变量和方法的调用
    悲观锁和乐观锁
    Java实现冒泡排序、折半查找
    (转载)Java 自动装箱与拆箱、equals和==的比较
    编程之美:数组分割
    windows下perl的安装和脚本的运行
  • 原文地址:https://www.cnblogs.com/webabcd/p/1217107.html
Copyright © 2020-2023  润新知