有時候在編寫線程並發的時候需要考慮異步和同步的問題。有些資源只能是一個線程訪問,其他的線程在這個線程沒有釋放資源前不能訪問。類似於操作系統中臨界資源的訪問。C#Lock包裹的代碼塊具有原子操作的特性(要么執行到結束為止,要么不執行)。
舉個列子:銀行賬戶的余額就是典型的臨界資源的問題,假如原本有1000,你的情婦A,B先后打500給你。A打500的這個操作是一個線程,從數據庫取出余額的值累加正准備寫回數據庫的時候,由於某種原因(時間片用完、來了更高的優先級的線程)阻塞,這時候B又給你打500,他得到余額依然是1000,累加后寫回數據庫1500到手。這時剛才被阻塞的線程又獲得執行權,將1500寫回數據庫。你莫名奇妙少了500,回去找情婦理論是沒有結果的,銀行系統的鍋。
Lock可以運用在單列模式上。剛開始我一直納悶Lock括號里面究竟寫什么,經同學指點。大概是任意不會改變的對象(里面寫一個固定的字符串”999“也可以)
那個對象是一把鎖。它會把鑰匙給第一個訪問它的進程,如果進程完事就上交鑰匙。有且只有一把鑰匙,實現了原子操作
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TestLock { class TestThread { private static TestThread instance; private static Object obj = new object(); private TestThread() { } public static void GetInstance() { if (instance == null)//先判斷,異步 { lock (obj)//任意不改變對象 { if (instance == null)//同步 { Console.WriteLine("初始化"); instance = new TestThread(); } } } } } }
Thread t1 = new Thread(TestThread.GetInstance); Thread t2 = new Thread(TestThread.GetInstance); Thread t3 = new Thread(TestThread.GetInstance); t1.Start(); t2.Start(); t3.Start();
結果是只打印一行初始化,如果沒有lock包裹那塊代碼那么結果會有三行初始化。因為,線程都會遇到if (instance == null)真