多線程程序是常常須要用到的,本文介紹C#使用Monitor類、Lock和Mutex類進行多線程同步。數據庫
在多線程中,爲了使數據保持一致性必需要對數據或是訪問數據的函數加鎖,在數據庫中這是很常見的,可是在程序中因爲大部分都是單線程的程序,因此沒有加鎖的必要,可是在多線程中,爲了保持數據的同步,必定要加鎖,好在Framework中已經爲咱們提供了三個加鎖的機制,分別是Monitor類、Lock關鍵字和Mutex類。 其中Lock關鍵詞用法比較簡單,Monitor類和Lock的用法差很少。這兩個都是鎖定數據或是鎖定被調用的函數。而Mutex則多用於鎖定多線程間的同步調用。簡單的說,Monitor和Lock多用於鎖定被調用端,而Mutex則多用鎖定調用端。 例以下面程序:因爲這種程序都是毫秒級的,因此運行下面的程序可能在不一樣的機器上有不一樣的結果,在同一臺機器上不一樣時刻運行也有不一樣的結果,個人測試環境爲vs2005, windowsXp , CPU3.0 , 1 G monery。 程序中有兩個線程thread一、thread2和一個TestFunc函數,TestFunc會打印出調用它的線程名和調用的時間(mm級的),兩個線程分別以30mm和100mm來調用TestFunc這個函數。TestFunc執行的時間爲50mm。程序以下:windows
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace MonitorLockMutex { class Program { #region variable Thread thread1 = null; Thread thread2 = null; Mutex mutex = null; #endregion static void Main(string[] args) { Program p = new Program(); p.RunThread(); Console.ReadLine(); } public Program() { mutex = new Mutex(); thread1 = new Thread(new ThreadStart(thread1Func)); thread2 = new Thread(new ThreadStart(thread2Func)); } public void RunThread() { thread1.Start(); thread2.Start(); } private void thread1Func() { for (int count = 0; count < 10; count++) { TestFunc("Thread1 have run " + count.ToString() + " times"); Thread.Sleep(30); } } private void thread2Func() { for (int count = 0; count < 10; count++) { TestFunc("Thread2 have run " + count.ToString() + " times"); Thread.Sleep(100); } } private void TestFunc(string str) { Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString()); Thread.Sleep(50); } } }
運行結果以下:多線程
private void TestFunc(string str) { lock (this) { Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString()); Thread.Sleep(50); } } 或者是用Monitor也是同樣的,以下: private void TestFunc(string str) { Monitor.Enter(this); Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString()); Thread.Sleep(50); Monitor.Exit(this); }
private void thread1Func() { for (int count = 0; count < 10; count++) { mutex.WaitOne(); TestFunc("Thread1 have run " + count.ToString() + " times"); mutex.ReleaseMutex(); } } private void thread2Func() { for (int count = 0; count < 10; count++) { mutex.WaitOne(); TestFunc("Thread2 have run " + count.ToString() + " times"); mutex.ReleaseMutex(); } } private void TestFunc(string str) { Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString()); Thread.Sleep(50); }
private void thread1Func() { for (int count = 0; count < 10; count++) { lock (this) { mutex.WaitOne(); TestFunc("Thread1 have run " + count.ToString() + " times"); mutex.ReleaseMutex(); } } } private void thread2Func() { for (int count = 0; count < 10; count++) { lock (this) { mutex.WaitOne(); TestFunc("Thread2 have run " + count.ToString() + " times"); mutex.ReleaseMutex(); } } }