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.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.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:本人水平有限,如果錯漏還請大家幫忙...