C#中lock逝世鎖實例教程。本站提示廣大學習愛好者:(C#中lock逝世鎖實例教程)文章只能為提供參考,不一定能成為您想要的結果。以下是C#中lock逝世鎖實例教程正文
在c#中有個症結字lock,它的感化是鎖定某一代碼塊,讓統一時光只要一個線程拜訪該代碼塊,本文就來談談lock症結字的道理和個中應留意的幾個成績:
lock的應用原型是:
lock(X) { //須要鎖定的代碼.... }
起首要明確為何下面這段話可以或許鎖定代碼,個中的奇妙就是X這個對象,現實上X是隨意率性一種援用類型,它在這兒起的感化就是任何線程履行到lock(X)時刻,X須要獨享能力運轉上面的代碼,若假定如今有3個線程A,B,C都履行到了lock(X)而ABC由於此時都占領X,這時候ABC就要停上去排個隊,一個一個應用X,從而起到鄙人面的代碼塊內只要一個線程在運轉(由於此時只要一個線程獨享X,其他兩個在列隊),所以這個X必需是一切要履行臨界區域代碼過程必需共有的一個資本,從而起到克制線程的感化。
上面再來談談lock應用中會碰到和留意的成績,lock最須要留意的一個成績就是線程逝世鎖!
在MSDN上列出了3個典范成績:
平日,應防止鎖定 public 類型,不然實例將超越代碼的掌握規模。罕見的構造 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 違背此原則:
假如實例可以被公共拜訪,將湧現 lock (this) 成績。
假如 MyType 可以被公共拜訪,將湧現 lock (typeof (MyType)) 成績。
因為過程中應用統一字符串的任何其他代碼將同享統一個鎖,所以湧現 lock(“myLock”) 成績。
最好做法是界說 private 對象來鎖定, 或 private shared 對象變量來掩護一切實例所共有的數據。
(1)lock (this) 成績:
假定有兩個類:
class A{} class B{}
有兩個公共對象:
A a=new A(); B b=new B();
起首在A中如有一函數內的代碼須要鎖定:
代碼1:
lock(this)//this在這裡就是a { //.... lock(b) { //...... } }
但是此時B中某函數也有以下代碼須要鎖定:
代碼2:
lock(this)//this在這裡就是b { //.... lock(a) { //...... } }
假想一下下面兩段代碼在兩個線程下同時履行會有甚麼效果?
成果就是,代碼1履行到lock(this)後a被鎖定,代碼2履行到lock(this)後b被鎖定,然子女碼1需求b,代碼2需求a,此時兩個需求都被互相占領湧現僵持狀況,法式逝世鎖了。
(2)lock(typeof (MyType))成績:
假定有兩個公共變量:
int a;float b;
上面看以下代碼
代碼3:
lock(typeof(a))//typeof(a)就是System.type.Int類型 { //.... lock(typeof(b)) { //...... } }
又有以下代碼:
代碼4:
lock(typeof(b))//typeof(b)就是System.type.Float類型 { //.... lock(typeof(a)) { //...... } }
如有兩個過程分離同時進入下面兩個代碼外層的lock,就分離鎖定了System.type.Int和System.type.Float,而立時它們又需求System.type.Float和System.type.Int,彼此互相占領,彼此僵持,法式進入逝世鎖狀況!
(3)字符串成績 :
在論述這個成績之前,有一個常識年夜家必需曉得:C#中字符串被公共說話運轉庫 (CLR)“暫留”。這意味著全部法式中任何給定字符串都只要一個實例,就是這統一個對象表現了一切運轉的運用法式域的一切線程中的該文本。是以,只需在運用法式過程中的任何地位處具有雷同內容的字符串上放置了鎖,就將鎖定運用法式中該字符串的一切實例。
言下之意就是假定有兩個類分離有兩個字符串:
class A { string a="abc"; string b="def"; } class c { string c="abc"; string d="def"; }
現實上a和c援用的是統一個字符串"abc",b和d援用的是統一個字符串"def"
如今假如在兩個類中有以下代碼
在類A中有代碼5:
lock(b)//b是"def" { //.... lock(a)//a是"abc" { //...... } }
在類B中有代碼6:
lock(c)//c是"abc" { //.... lock(d)//d是"def" { //...... } }
那末代碼5和代碼6同時有兩個線程履行成果可想而知:在兩個線程履行到外層lock代碼時"def"和"abc"被鎖定。接著他們在外部lock處同時需求"abc"和"def",而此時兩個字符串被兩個過程彼此占領,法式又逝世鎖了!所以MSDN說:鎖定字符串特別風險!最好不要應用!
MSDN最初說了:最好做法是界說 private 對象來鎖定, 或 private shared 對象變量來掩護一切實例所共有的數據。
在小我看來,也不是相對平安,這裡就舉出一個例子:
假定有一個類:
class A { private Object a=new Object(); private Object b=new Object(); public void x() { lock(a) { //..... lock(b) { //.... } } } public void y() { lock(b) { //..... lock(a) { //.... } } } }
如今假定有兩個線程同時履行函數x()和y();成果private對象a和b分離在外層lock鎖定,接著兩個線程在外部又立馬需求b和a,a,b彼此占領又彼此需求,法式逝世鎖。
所以詳細要看情形而定,然則界說 private 對象來鎖定至多可以下降風險。
願望本文所述C#中lock的運用對年夜家的C#法式設計有所贊助。