C# 使用lock關鍵字lock不同的對象

來源:互聯網
上載者:User

c# lock關鍵字的本質

是調用Monitor.Enter(object obj)並且在finally的時候調用Monitor.Exit(obj)

 

在obj是不同資料類型的時候會出現不同的情況

1.鎖定類型 例如lock(typeof(int))  lock(typeof(ClassA))   // CalssA 是一個類的定義

  備忘:前者作用範圍跨AppDomain 不跨Process, 後者不跨AppDomain(預設設定)

  使用範圍:絕不推薦使用

2.鎖定字串 例如lock("abc") 和lock(s)//s是一個字串的執行個體變數

  備忘:當字串已經駐留在記憶體的時候 這個lock是有效, 如果字串未駐留在記憶體那麼這個lock就失效了,該lock是跨Appdomain不跨Process

  使用範圍: 一般不推薦使用

  以下代碼顯示了非駐留字串導致的無法lock的問題,請在實際應用中避免lock(a+b)即使他們的值一樣 (vs2008 Debug)

 

 

代碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string s1 = "a";
string s2 = "bc";

ThreadPool.QueueUserWorkItem(p =>
{
Thread.Sleep(3000); Console.WriteLine(" Thread2 Begin Test");
lock (s1 + s2)
{
Console.WriteLine("Thread2 Begin Lock");
Thread.Sleep(1000);
Console.WriteLine("Thread2 End Lock");
}
});
Console.WriteLine("Thread1 Begin Test");
lock (s1 + s2)
{
Console.WriteLine("Thread1 Begin Lock");
Thread.Sleep(10000);
Console.WriteLine("Thread1 End Lock");
}
}
}
}

 

3.所有繼承於System.MarshalByRefObject 的對象  ,例如Remoting Service之類的

  備忘:鎖定的是代理對象,在遠端的對象並沒有被鎖定(byValue 和byRef 兩種類型傳資料也有影響)

  使用範圍:不推薦

4.實值型別, 由於眾所周知的裝箱的問題...實際上鎖定根本不生效

  使用範圍:不推薦

5. 應用[MethodImpl(MethodImplOptions.Synchronized)]標記的類

  執行個體方法鎖定的是this   lock(this)

  靜態方法鎖定的是typeof(ClassName)   lock(typeof(ClassName)) //ClassName是你當前的類名

  使用範圍:不推薦, 調用靜態方法將導致鎖定類型, 執行個體方法之間也相互影響鎖定關係

6.lock(this)

  很容易誤用,例如在web page上調用 lock(this)....由於asp.net會為每次httpRequest , new一個類的執行個體...所以lock(this)在這裡一點作用都沒有

  在其他的情況下:lock(this)鎖定了本身,那麼但其他外部對象試圖使用這個類的時候會有困擾

  如果你的類是public給其他人用的,那麼最好不要lock(this)

  請參考以下代碼(不推薦使用)

  

代碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
public class ClassA
{
public void Test()
{
lock (this)
{
Console.WriteLine("Test Begin Lock");
Thread.Sleep(10000);
Console.WriteLine("Test End Lock");
}
}
}
class Program
{
static void Main(string[] args)
{
ClassA classA = new ClassA();

ThreadPool.QueueUserWorkItem(p =>
{
Thread.Sleep(3000); Console.WriteLine(" Thread2 Begin Test");
lock (classA)
{
Console.WriteLine("Thread2 Begin Lock");
Thread.Sleep(1000);
Console.WriteLine("Thread2 End Lock");
}
});
classA.Test();
Console.ReadLine();
}
}
}

7. lock(null) 必然拋出一個異常

8.推薦使用以下方法lock

  private static object asyncLock=new object();

  lock(asyncLock)

  使用 private object asyncLock=new object(); 也是ok的,但是請注意避免之前提到的WebPage每次new一個類導致lock失效的問題

  影響範圍不跨AppDomain

 

 

  PS1:關於跨不跨AppDomain的問題,其實用處不大,大部分應用程式都只是建立一個DefaultDomain

  PS2:可以將一些Assembly設定為跨AppDomain的,以減少記憶體浪費和提高效能, 例如string和一些基本類型都是這樣實現的

  PS3:本人水平有限,如果錯漏還請大家幫忙...

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.