上一章我們講到關於C#線程方向的應用。但是筆者並沒有講到多線程中的另一個知識點——同步。多線程的應用開發都有可能發生臟數據。同步的功能或多或少都會用到。本章就要來講一下關於線程同步的問題。根據筆者這幾年來的.NET開發可以瞭解到的同步方式至少有四種以上。如。lock、volatile、Monitor ...
上一章我們講到關於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 正在運行中"); //內容 } }
本章總結 |
本章主要介紹關於線程之間同步數據的一些常用的方式。當然以上只是筆者常用到的而以。並不全面。好了本章就到這裡了。