<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
{
/// <summary>
/// 鎖 類型的枚舉
/// </summary>
[DataContract]
public enum LockType
{
/// <summary>
/// 不使用任何并發控制
/// </summary>
[EnumMember]
None,
/// Mutex
Mutex,
/// Semaphore
Semaphore,
/// Monitor
Monitor,
/// Lock
Lock
}
}
IHello.cs
/// 示範并發控制(鎖)的接口
[ServiceContract]
public interface IHello
/// 計數器
/// <param name="lockType">鎖的類型</param>
[OperationContract]
void Counter(LockType lockType);
/// 擷取計數器被調用的結果
/// <returns></returns>
string GetResult();
/// 清空計數器和結果
void CleanResult();
Hello.cs
/// <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();
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 < 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
<%@ 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>
<li>Mutex - 提供對資源的獨占通路</li>
<li>Semaphore - 限制可同時通路某一資源或資源池的線程數</li>
<li>Monitor - 提供同步通路對象的機制</li>
<li>Lock - 關鍵字将語句塊标記為臨界區,方法是擷取給定對象的互斥鎖,執行語句,然後釋放該鎖</li>
<li>ThreadPool - 提供一個線程池,該線程池可用于發送工作項、處理異步 I/O、代表其他線程等待以及處理計時器</li>
<li>Interlocked - 為多個線程共享的變量提供原子操作</li>
<li>ReaderWriterLock - 定義支援單個寫線程和多個讀線程的鎖</li>
</asp:Content>
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 < 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)
// 清空計數器和結果
proxy.CleanResult();
txtResult.Text = "";
<client>
<!--address - 服務位址-->
<!--binding - 通信方式-->
<!--contract - 服務契約-->
<endpoint address="http://localhost:3502/ServiceHost/ConcurrencyLock/Hello.svc" binding="basicHttpBinding" contract="ConcurrencyLockSvc.IHello" />
</client>
運作結果:
單擊"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,如需轉載請自行聯系原作者