[C#.NET][Thread] 小心使用執行緒的鎖定物件

[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();
    }
}

上段程式碼的執行結果如下:

 

SNAGHTML131e0c48

 

 

使用靜態變數鎖定的結果,讓不同的執行個體都參考了同一個鎖定物件,這帶來了一個問題,每當程式設計師使用這個類別,呼叫非靜態方法時,都會遇到這個鎖,都會同步,這就失去了我們的目的

 

  • 要完成非靜態方法在多執行緒下,能在不同的執行個體能各自工作,只要將 s_lock 的 static 拿掉就好了。
  • 靜態方法要確保執行緒安全,則用靜態的物件來鎖定,若DoWork是靜態方法,s_lock 就不需要改變。

 

將 s_lock 的 static 拿掉的執行結果

SNAGHTML132b0e1d

 

 

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo