锁、C#中Monitor和Lock以及区别
1.Monitor.Enter(object)方法是獲取鎖,Monitor.Exit(object)方法是釋放鎖,這就是Monitor最常用的兩個(gè)方法,當(dāng)然在使用過程中為了避免獲取鎖之后因?yàn)楫惓?#xff0c;致鎖無法釋放,所以需要在try{} catch(){}之后的finally{}結(jié)構(gòu)體中釋放鎖(Monitor.Exit())。
2.Monitor的常用屬性和方法:
Enter(Object) 在指定對象上獲取排他鎖。
Exit(Object) 釋放指定對象上的排他鎖。
IsEntered 確定當(dāng)前線程是否保留指定對象鎖。
Pulse 通知等待隊(duì)列中的線程鎖定對象狀態(tài)的更改。
PulseAll 通知所有的等待線程對象狀態(tài)的更改。
TryEnter(Object) 試圖獲取指定對象的排他鎖。
TryEnter(Object, Boolean) 嘗試獲取指定對象上的排他鎖,并自動(dòng)設(shè)置一個(gè)值,指示是否得到了該鎖。
Wait(Object) 釋放對象上的鎖并阻止當(dāng)前線程,直到它重新獲取該鎖。
Lock關(guān)鍵字1.Lock關(guān)鍵字實(shí)際上是一個(gè)語法糖,它將Monitor對象進(jìn)行封裝,給object加上一個(gè)互斥鎖,A進(jìn)程進(jìn)入此代碼段時(shí),會(huì)給object對象加上互斥鎖,此時(shí)其他B進(jìn)程進(jìn)入此代碼段時(shí)檢查object對象是否有鎖?如果有鎖則繼續(xù)等待A進(jìn)程運(yùn)行完該代碼段并且解鎖object對象之后,B進(jìn)程才能夠獲取object對象為其加上鎖,訪問代碼段。
2.Lock關(guān)鍵字封裝的Monitor對象結(jié)構(gòu)如下:
try{Monitor.Enter(obj);dosomething();}catch(Exception ex){}finally{Monitor.Exit(obj);}3.鎖定的對象應(yīng)該聲明為private static object obj = new object();盡量別用公共變量和字符串、this、值類型。
Monitor和Lock的區(qū)別
1.Lock是Monitor的語法糖。
2.Lock只能針對引用類型加鎖。
3.(使用?Monitor?鎖定對象(即引用類型)而不是值類型。)。
4.Monitor還有其他的一些功能。
class Program{private static object obj = new object();public void LockSomething(){lock (obj){dosomething();}}public void MonitorSomeThing(){try{Monitor.Enter(obj);dosomething();}catch(Exception ex){}finally{Monitor.Exit(obj);}}public void dosomething(){ //做具體的事情 }}Monitor?類通過向單個(gè)線程授予對象鎖來控制對對象的訪問。對象鎖提供限制訪問代碼塊(通常稱為臨界區(qū))的能力。當(dāng)一個(gè)線程擁有對象的鎖時(shí),其他任何線程都不能獲取該鎖。還可以使用?Monitor?來確保不會(huì)允許其他任何線程訪問正在由鎖的所有者執(zhí)行的應(yīng)用程序代碼節(jié),除非另一個(gè)線程正在使用其他的鎖定對象執(zhí)行該代碼。
Monitor?具有以下功能:
-
它根據(jù)需要與某個(gè)對象相關(guān)聯(lián)。
-
它是未綁定的,也就是說可以直接從任何上下文調(diào)用它。
-
不能創(chuàng)建?Monitor?類的實(shí)例。
將為每個(gè)同步對象來維護(hù)以下信息:
-
對當(dāng)前持有鎖的線程的引用。
-
對就緒隊(duì)列的引用,它包含準(zhǔn)備獲取鎖的線程。
-
對等待隊(duì)列的引用,它包含正在等待鎖定對象狀態(tài)變化通知的線程。
-
下表描述了訪問同步對象的線程可以采取的操作:
操作
說明
Enter,?TryEnter
獲取對象鎖。此操作同樣會(huì)標(biāo)記臨界區(qū)的開頭。其他任何線程都不能進(jìn)入臨界區(qū),除非它使用其他鎖定對象執(zhí)行臨界區(qū)中的指令。
Wait
釋放對象上的鎖以便允許其他線程鎖定和訪問該對象。在其他線程訪問對象時(shí),調(diào)用線程將等待。脈沖信號(hào)用于通知等待線程有關(guān)對象狀態(tài)的更改。
Pulse?(信號(hào)),?PulseAll
向一個(gè)或多個(gè)等待線程發(fā)送信號(hào)。該信號(hào)通知等待線程鎖定對象的狀態(tài)已更改,并且鎖的所有者準(zhǔn)備釋放該鎖。等待線程被放置在對象的就緒隊(duì)列中以便它可以最后接收對象鎖。一旦線程擁有了鎖,它就可以檢查對象的新狀態(tài)以查看是否達(dá)到所需狀態(tài)。
Exit
釋放對象上的鎖。此操作還標(biāo)記受鎖定對象保護(hù)的臨界區(qū)的結(jié)尾。
使用?Enter?和?Exit?方法標(biāo)記臨界區(qū)的開頭和結(jié)尾。如果臨界區(qū)是一個(gè)連續(xù)指令集,則由?Enter?方法獲取的鎖將保證只有一個(gè)線程可以使用鎖定對象執(zhí)行所包含的代碼。在這種情況下,建議您將這些指令放在?try?塊中,并將?Exit?指令放在?finally?塊中。此功能通常用于同步對類的靜態(tài)或?qū)嵗椒ǖ脑L問。如果實(shí)例方法需要同步線程訪問,則它將使用當(dāng)前實(shí)例作為要鎖定的對象調(diào)用?Enter?和對應(yīng)的?Exit?方法。由于只能有一個(gè)線程持有當(dāng)前實(shí)例上的鎖,因此該方法一次只能由一個(gè)線程來執(zhí)行。靜態(tài)方法是使用當(dāng)前實(shí)例的?Type?作為鎖定對象以類似的方式來保護(hù)的。Enter?和?Exit?方法提供的功能與 C#?lock?語句(在 Visual Basic 中為?SyncLock)提供的功能相同,區(qū)別在于?lock?和?SyncLock?以?try…finally?塊(在 Visual Basic 中為?Try…Finally)來包裝?Exit?方法,以確保釋放監(jiān)視器。
如果臨界區(qū)跨越整個(gè)方法,則可以通過將?System.Runtime.CompilerServices.MethodImplAttribute?放置在方法上并在?MethodImplAttribute?的構(gòu)造函數(shù)中指定?Synchronized?值來實(shí)現(xiàn)上述鎖定功能。使用該屬性后就不需要?Enter?和?Exit?語句了。請注意,該屬性將使當(dāng)前線程持有鎖,直到方法返回;如果可以更早釋放鎖,則使用?Monitor?類或 C#lock?語句而不是該屬性。
盡管鎖定和釋放給定對象的?Enter?和?Exit?語句可以跨越成員或類的邊界或同時(shí)跨越兩者的邊界,但并不推薦這樣做。
當(dāng)選擇要同步的對象時(shí),應(yīng)只鎖定私有或內(nèi)部對象。鎖定外部對象可能導(dǎo)致死鎖,這是因?yàn)椴幌嚓P(guān)的代碼可能會(huì)出于不同的目的而選擇鎖定相同的對象。
- 以上來自MSDN、
- @陳臥龍的博客
總結(jié)
以上是生活随笔為你收集整理的锁、C#中Monitor和Lock以及区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 正则扩展学习
- 下一篇: IDC:全球经济危机为云计算带来曙光