2013-01-07 66 views
8

後,我看了與an answer從馬克this問題....鎖定字段或局部變量?

我有時會看到人鎖定在一個本地變量。

這段代碼被破壞了嗎?

public void Do() 
{ 
object o = new Object(); 
lock (o) 
    { 
     ... 
    } 
} 

我相信object o = new Object();應該的方法作爲Field

因爲每個線程得到的o一個新實例,將有多個鎖。

缺少什麼我在這裏?它不應該鎖定在這個特定情況下的字段嗎?

回答

8

相信對象o =新對象();應作爲字段在方法之外。

因爲每個線程越來越鄰的新實例,將有多個鎖。

有什麼我錯過這裏?因爲我知道它應該鎖定在字段上(在這個特定的情況下)。

你的理解是正確的。代碼被破壞。在此實現中,即使鎖定處於活動狀態,它也不會提供同步,因爲它將位於不同的對象上。

MSDN-lock c#

一般情況下,避免鎖定在一個公共類型,或者超出你的代碼的控制情況。共同構建鎖(本),鎖(typeof運算(的MyType)),並鎖定(「myLock」)違反此準則:

  • 鎖(這)是一個問題,如果該實例可以公開訪問。
  • 如果MyType是可公開訪問的,則鎖定(typeof(MyType))是一個問題。
  • 鎖(「myLock」)是一個問題,因爲使用相同字符串的進程中的任何其他代碼將共享相同的鎖。

最佳做法是定義要鎖定的私有對象或私有靜態對象變量以保護所有實例的公共數據。

2

你正在創建每次你的方法被調用時O對象。所以,鎖定將不起作用。我的意思是其他線程不會等待該鎖被非信號發送,並且抓住該鎖控制的資源的控制權。通常,鎖對象是一個類中的私有變量,以便所有方法都可以查看同一個對象。

2

我個人而言,看不出有任何理由使用這個,因爲lock只是設置了專業的實例o,對信號狀態。所以其他線程可以檢查該實例的狀態,並根據該語句執行lock語句中的代碼或等待釋放它。

每次都會分配一個新的實例,因此對於每一個線程這將是確定有局部變量。

看不到在這沒有任何意義。

5

是的。它被打破。

你想要一個靜態只讀對象作爲私有字段來鎖定。正如你懷疑的那樣,你的示例代碼在你每次調用Do的時候都會創建一個新的對象,因此這個鎖將沒有任何東西可以保存,並且根本無法工作。

private static object syncRoot = new object(); 

lock (syncRoot) { } 
+0

它不一定是靜態的。 (除非針對不同的實例) –

+0

使其靜態只讀不會損害它,只是保護它(儘管它不是必需的) – Tilak

+2

同意。它不一定是靜態的。取決於你所保護的內容。 –

1

鎖定本地變量,鎖贏得了工作。鎖定全局變量可以生效以同步多個線程。

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

     namespace testLock 
     { 
      class Program 
      { 
       public static void Main() 
       { 
        // Start a thread that calls a parameterized static method. 
        for(int i = 0; i< 10;i++) 
        { 
         Thread newThread = new Thread(DoWork); 
         newThread.Start(i); 
        } 

        Console.ReadLine(); 
       } 

       static object gObject= new object(); 
       public static void DoWork(object data) 
       { 
        int len = (int)data % 3; 
        object tmp = new object(); 
        Console.WriteLine("to lock...... Data='{0}' sleepTime:{1}", data, len); 
        lock (tmp)//tmp won't work, change tmp to gObject to see different output, which is good locking case) 
        { 
         Console.WriteLine("in lock...... Data='{0}' sleepTime:{1}", data, len); 

         Thread.Sleep( len* 1000); 
         Console.WriteLine("Static thread procedure. Data='{0}' sleepTime:{1}", data, len); 
        } 
       } 

      } 
     } 

    **Lock temp variable,will output:** 
    to lock...... Data='1' sleepTime:1 
    in lock...... Data='1' sleepTime:1 
    to lock...... Data='2' sleepTime:2 
    in lock...... Data='2' sleepTime:2 
    to lock...... Data='0' sleepTime:0 
    in lock...... Data='0' sleepTime:0 
    Static thread procedure. Data='0' sleepTime:0 
    to lock...... Data='3' sleepTime:0 
    in lock...... Data='3' sleepTime:0 
    Static thread procedure. Data='3' sleepTime:0 
    to lock...... Data='4' sleepTime:1 
    in lock...... Data='4' sleepTime:1 
    to lock...... Data='5' sleepTime:2 
    in lock...... Data='5' sleepTime:2 
    to lock...... Data='6' sleepTime:0 
    in lock...... Data='6' sleepTime:0 
    Static thread procedure. Data='6' sleepTime:0 
    to lock...... Data='7' sleepTime:1 
    in lock...... Data='7' sleepTime:1 
    to lock...... Data='8' sleepTime:2 
    in lock...... Data='8' sleepTime:2 
    to lock...... Data='9' sleepTime:0 
    in lock...... Data='9' sleepTime:0 
    Static thread procedure. Data='9' sleepTime:0 
    Static thread procedure. Data='1' sleepTime:1 
    Static thread procedure. Data='4' sleepTime:1 
    Static thread procedure. Data='7' sleepTime:1 
    Static thread procedure. Data='2' sleepTime:2 
    Static thread procedure. Data='5' sleepTime:2 
    Static thread procedure. Data='8' sleepTime:2 

    **Then lock gObject, will print:** 
    to lock...... Data='0' sleepTime:0 
    in lock...... Data='0' sleepTime:0 
    to lock...... Data='1' sleepTime:1 
    to lock...... Data='2' sleepTime:2 
    Static thread procedure. Data='0' sleepTime:0 
    in lock...... Data='1' sleepTime:1 
    to lock...... Data='3' sleepTime:0 
    to lock...... Data='4' sleepTime:1 
    to lock...... Data='5' sleepTime:2 
    to lock...... Data='6' sleepTime:0 
    to lock...... Data='7' sleepTime:1 
    to lock...... Data='8' sleepTime:2 
    to lock...... Data='9' sleepTime:0 
    Static thread procedure. Data='1' sleepTime:1 
    in lock...... Data='5' sleepTime:2 
    Static thread procedure. Data='5' sleepTime:2 
    in lock...... Data='9' sleepTime:0 
    Static thread procedure. Data='9' sleepTime:0 
    in lock...... Data='2' sleepTime:2 
    Static thread procedure. Data='2' sleepTime:2 
    in lock...... Data='8' sleepTime:2 
    Static thread procedure. Data='8' sleepTime:2 
    in lock...... Data='7' sleepTime:1 
    Static thread procedure. Data='7' sleepTime:1 
    in lock...... Data='4' sleepTime:1 
    Static thread procedure. Data='4' sleepTime:1 
    in lock...... Data='3' sleepTime:0 
    Static thread procedure. Data='3' sleepTime:0 
    in lock...... Data='6' sleepTime:0 
    Static thread procedure. Data='6' sleepTime:0 
+0

C#中沒有全局變量。 – Enigmativity

+1

你是對的,這個例子中的全局變量我的意思是類Program中的靜態變量。 – terwxqian