欧美成人亚洲综合在线-91麻豆果冻精品一区二区三区-欧美性生活视频69-中国一级毛片视频免费看-欧洲精品一区二区三区中文字幕-国产精品剧情在线第一页-精品丰满熟女一区二区三区蜜桃-人妻日韩精品中文字幕-亚洲中文字幕五月婷婷

新聞

C# 說說lock到底應(yīng)該鎖誰?

發(fā)布時間

2019-08-28

來源

來自銘成奇跡

移動

手機閱覽

最近一個月一直在弄文件傳輸組件,其中用到多線程的技術(shù),但有的地方確實需要只能有一個線程來操作,如何才能保證只有一個線程呢?首先想到的就是鎖的概念,最近在我們項目組中聽的最多的也是鎖誰,如何鎖?看到有同事使用lock(this),也有l(wèi)ock(private static object),那就有點困惑了,lock到底鎖誰才是最合適的呢?


lock



首先先上官方Msdn的說法


lock 關(guān)鍵字可確保當(dāng)一個線程位于代碼的臨界區(qū)時,另一個線程不會進入該臨界區(qū)。 如果其他線程嘗試進入鎖定的代碼,則它將一直等待(即被阻止),直到該對象被釋放。

lock 關(guān)鍵字在塊的開始處調(diào)用 Enter,而在塊的結(jié)尾處調(diào)用 Exit。 ThreadInterruptedException 引發(fā),如果 Interrupt 中斷等待輸入 lock 語句的線程。

通常,應(yīng)避免鎖定 public 類型,否則實例將超出代碼的控制范圍。


常見的結(jié)構(gòu) lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 違反此準(zhǔn)則:

如果實例可以被公共訪問,將出現(xiàn) lock (this) 問題。

如果 MyType 可以被公共訪問,將出現(xiàn) lock (typeof (MyType)) 問題。

由于進程中使用同一字符串的任何其他代碼都將共享同一個鎖,所以出現(xiàn) lock("myLock") 問題。

最佳做法是定義 private 對象來鎖定, 或 private static 對象變量來保護所有實例所共有的數(shù)據(jù)。

在 lock 語句的正文不能使用 等待 關(guān)鍵字。


Enter指的是Monitor.Enter(獲取指定對象上的排他鎖。),Exit指的是Monitor.Exit(釋放指定對象上的排他鎖。)


有上面msdn的解釋及Exit方法,可以這樣猜測“直到該對象被釋放”,”該對象“應(yīng)該是指鎖的對象,對象釋放了或者對象改變了,其他的線程才可以進入代碼臨界區(qū)(是不是可以這樣來理解?)。


在多線程中,每個線程都有自己的資源,但是代碼區(qū)是共享的,即每個線程都可以執(zhí)行相同的函數(shù)。這可能帶來的問題就是幾個線程同時執(zhí)行一個函數(shù),導(dǎo)致數(shù)據(jù)的混亂,產(chǎn)生不可預(yù)料的結(jié)果,因此我們必須避免這種情況的發(fā)生。


打個比方,有這樣一個情景,很多公司所在的大廈的廁所的蹲位都是小單間型的,也就是一次只能進去一個人,那么為了避免每次進去一個人,那怎么做呢?不就是一個人進去之后順手把門鎖上么?這樣你在里面干啥事,外邊的人也只能等待你解放完了,才能進入。而蹲位的資源(蹲位,手紙等)是共享的。


最常使用的鎖是如下格式的代碼段:

private static object objlock = new object();lock (objlock ){ //要執(zhí)行的代碼邏輯}
為什么鎖的對象是私有的呢?還是以廁所為例子吧,私有就好比,這把鎖只有你能訪問到,而且最好這把鎖不會因為外力而有所改變,別人訪問不到,這樣才能保證你進去了,別人就進不去了,如果是公有的,就好比你蹲位小單間的鎖不是安裝在里面而是安裝在外邊的,別人想不想進就不是你所能控制的了,這樣也不安全。




上面說的最多的是lock對象,那么它能不能lock值類型?

答案是否定的,如



當(dāng)然lock(null)也是不行的,如圖


雖然編譯可以通過,但是運行就會出錯。


lock(string)

string也是應(yīng)用類型,從語法上來說是沒有錯的。

但是鎖定字符串尤其危險,因為字符串被公共語言運行庫 (CLR)“暫留”。 這意味著整個程序中任何給定字符串都只有一個實例,就是這同一個對象表示了所有運行的應(yīng)用程序域的所有線程中的該文本。因此,只要在應(yīng)用程序進程中的任何位置處具有相同內(nèi)容的字符串上放置了鎖,就將鎖定應(yīng)用程序中該字符串的所有實例。通常,最好避免鎖定 public 類型或鎖定不受應(yīng)用程序控制的對象實例。例如,如果該實例可以被公開訪問,則 lock(this) 可能會有問題,因為不受控制的代碼也可能會鎖定該對象。這可能導(dǎo)致死鎖,即兩個或更多個線程等待釋放同一對象。出于同樣的原因,鎖定公共數(shù)據(jù)類型(相比于對象)也可能導(dǎo)致問題。而且lock(this)只對當(dāng)前對象有效,如果多個對象之間就達不到同步的效果。lock(typeof(Class))與鎖定字符串一樣,范圍太廣了。

總結(jié)



關(guān)于lock的介紹就到這里,有下面幾點需要注意的地方

1、lock的是引用類型的對象,string類型除外。

2、lock推薦的做法是使用靜態(tài)的、只讀的、私有的對象。

3、保證lock的對象在外部無法修改才有意義,如果lock的對象在外部改變了,對其他線程就會暢通無阻,失去了lock的意義。

@Aulan
this 表示的就是當(dāng)前實例,當(dāng)你再new一個的時候,鎖定的就不再是同一個對象了。 不能鎖定值類型的原因是,當(dāng)這個值類型傳遞到另一個線程的時候,會創(chuàng)建一個副本,鎖定的也不再是同一個對象了。 鎖定字符串帶來的問題是,字符串在CLR中會暫存在 內(nèi)存中,如果有兩個變量被分配了相同的字符串內(nèi)容,那么這兩個引用會指向同一塊內(nèi)存,實際鎖定也就是同一個對象,這就會導(dǎo)致整個應(yīng)用程序的阻塞。所以鎖定字符串是非常危險的行為。


資訊列表

其他的資訊
OTHER