上一章我們講到關於C#線程方向的應用。但是筆者並沒有講到多線程中的另一個知識點——同步。多線程的應用開發都有可能發生髒數據。同步的功能或多或少都會用到。本章就要來講一下關於線程同步的問題。根據筆者這幾年來的.NET開發可以了解到的同步方式至少有四種以上。如。lock、volatile、Monitor等。
lock方式對lock的關鍵字作用跟JAVA的synchronized關鍵字類似。但有一定的差別。JAVA的synchronized關鍵字可能修飾在方法上面。可惜C#卻不能修飾在方法上面。用法有什麼不同嗎。那不如讓我們看一下代碼?
C#:
lock (aomiLock) { Thread.Sleep(300000); i++; Console.WriteLine(aomiLock.Name); }
上面的aomiLock只是一個筆者定義類的一個實例而以。顯然筆者是看不出寫法上有多大的的區別。對於lock的用法,有一個新人這樣子問我:如果我有倆個靜態的全局變量。一個用去作lock的參數值。即是上面的aomiLock變理的位置。另一個在lock內部。即是大括號裡面。那麼可以在別的地方修改lock內部的值呢?我只能跟他說聲對不起。可以修改的。
注意:上面有說到volatile關鍵字事實在JAVA也有volatile關鍵字。都是作用於變量級別的。作用只是讓變理可見。這一點跟JAVA是一樣子。同時如果你想用跟synchronized關鍵字一樣子修飾在方法上面的話。不好意思請用[MethodImpl(MethodImplOptions.Synchronized)]。
Monitor類Monitor類在使用上跟locak的關鍵字有一點像。只是Monitor類本身提供了太多靈活的功能。大家是否知道JAVA 5.0之後提供的一個叫Lock接口。他的實例類ReentrantLock。他的功能就跟Monitor類類似。
bool acquireLock = false; Monitor.Enter(aomiLock, ref acquireLock); //內容 i++; Console.WriteLine("add i=" + i); Monitor.Exit(aomiLock);Mutex類
這是一個互斥鎖,筆者很少用他來作同步。Mutex類的作用可以到進程之間。所以更多的是被用在一個電腦只能運行一個應用程序的功能上。而且他用的資源比較大。但筆者沒有辦法證明。總之筆者很少用他就對了。
1 class Program 2 { 3 public static Mutex mutex; 4 static void Main(string[] args) 5 { 6 bool created; 7 mutex = new Mutex(false, "aomiApplication", out created); 8 9 Console.ReadKey(); 10 11 } 12 13 public static void Add() 14 { 15 for (int i = 0; i < 10; i++) 16 { 17 mutex.WaitOne(); 18 Console.WriteLine("add i=" + i); 19 mutex.ReleaseMutex(); 20 21 } 22 23 } 24 }
Mutex類的構造函數第一個參數用於表示。是否在新建Mutex類的時候就獲得互斥權利。true表示立即獲得。false的話則用WaitOne方法來獲得。相信筆者不用多說大家也明白。
SemaphoreSlim類SemaphoreSlim類筆者覺得他是一個控制線程量的一個類。他常常用於控制在當前應用最多能運行幾個線程或異步運行的數量。筆者更多的用於設計公司的框架的時候應用。
class Program { public static SemaphoreSlim ss = new SemaphoreSlim(4); static void Main(string[] args) { for (int i = 0; i < 10; i++) { Thread thread = new Thread(Add); thread.Start(); } Console.ReadKey(); } public static void Add() { if (ss.Wait(2000)) { Console.WriteLine("正在運行中"); Thread.Sleep(2000); ss.Release(); } else { Console.WriteLine("線程忙"); } } }AutoResetEvent類
筆者個人認為這個類不屬於同步類裡面的。更覺得他是一個信號燈的一個概念。可是他卻也能實現小功能的同步工作。在設計框架的時候筆者也常常用到。
class Program { public static AutoResetEvent mainEvent = new AutoResetEvent(false); static void Main(string[] args) { Thread thread = new Thread(Execute); thread.Start(); mainEvent.Set();//通知他可以很執行了 Console.ReadKey(); } public static void Execute() { mainEvent.WaitOne(); Console.WriteLine("Execute 正在運行中"); //內容 } }本章總結
本章主要介紹關於線程之間同步數據的一些常用的方式。當然以上只是筆者常用到的而以。並不全面。好了本章就到這裡了。