程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WCF示例(13) - 並發控制(鎖)

WCF示例(13) - 並發控制(鎖)

編輯:關於.NET

並發控制(鎖)(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
{
  /**//// <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(1, 1);
  
    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="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

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved