[C#.NET][Thread] 小心使用執行緒的鎖定物件
假設我對一個耗時的工作使用了ThreadPool,當我實體化多個執行個體時,不同的執行個體都要能各自工作。
public class DemoClass
{
private static object s_lock = new object();
private ulong m_value = 0;
public void DoWork(string name)
{
ThreadPool.QueueUserWorkItem(o =>
{
lock (s_lock)
{
for (ulong i = 0; i < 1000000; i++)
{
m_value = i;
Console.WriteLine(string.Format("{0} method value = {1}", name, m_value));
Thread.Sleep(1000);
}
}
});
}
}
實體化類別
internal class Program
{
private static void Main(string[] args)
{
DemoClass c1 = new DemoClass();
DemoClass c2 = new DemoClass();
c1.DoWork("NO.1");
Thread.Sleep(1000);
c2.DoWork("NO.2");
Console.ReadKey();
}
}
上段程式碼的執行結果如下:
使用靜態變數鎖定的結果,讓不同的執行個體都參考了同一個鎖定物件,這帶來了一個問題,每當程式設計師使用這個類別,呼叫非靜態方法時,都會遇到這個鎖,都會同步,這就失去了我們的目的
- 要完成非靜態方法在多執行緒下,能在不同的執行個體能各自工作,只要將 s_lock 的 static 拿掉就好了。
- 靜態方法要確保執行緒安全,則用靜態的物件來鎖定,若DoWork是靜態方法,s_lock 就不需要改變。
將 s_lock 的 static 拿掉的執行結果
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET