2009-08-25 85 views
6

比方說,我有以下代碼線程是否在鎖FIFO上等待?

static class ... 
{ 
    static object myobj = new object(); 

    static void mymethod() 
    { 
     lock(myobj) 
     { 
      // my code.... 
     } 
    } 
} 

然後讓我們說,雖然線程1具有線程2試圖運行的MyMethod鎖。 它會等待鎖釋放或拋出異常嗎?

如果確實等待,請確保順序,以便如果有其​​他線程進來,它們是FIFO?

回答

8

更新了我的回答: 他們排隊,但訂單不保證是FIFO。

退房此鏈接:http://www.albahari.com/threading/part2.aspx

+4

不一定,請參閱:http://stackoverflow.com/questions/961869/is-there-a-synchronization-class-that-guarantee-fifo-order-in-c/961904 – 2009-08-25 20:47:26

-1

它會等待,他們不會以相同的順序。

根據您的需求,你可能會如果你看看像以外的ReaderWriterLock或東西有更多的表現只是lock

+1

他們是不一樣的訂購。 – 2009-08-25 20:56:22

3

它是不是從你的代碼清楚如何myobj獲得可見裏面mymethod。看起來像var myobj是聲明範圍內的本地堆棧變量(因爲是var)。在這種情況下,可能每個線程都有一個單獨的實例,並且mymethod不會被阻止。

更新

關於整個FIFO的說法,一些背景信息是必要的:在CLR不提供同步化。它是CLR 主機,它將此作爲服務提供給CLR運行時。主機實現IHostSyncManager和其他接口並提供各種同步原語。由於最常見的主機是典型的應用程序主機(即,您編譯進入並執行exe),所以這可能看起來並不合適,並且這會影響與操作系統(Win32 API中的舊Petzold書籍原語)的所有同步。但是至少有兩個主要的託管環境:ASP.Net(我不確定這是什麼)和SQL Server。我可以肯定地告訴的是,SQL Server提供的SOS的託普所有原始數據(這基本上是一個用戶的多個操作系統),從來沒有接觸OS原語和SOS原語是由設計不公平,避免鎖車隊(即。保證沒有先入先出)。正如另一個響應中的鏈接已經指出的那樣,OS原語也開始提供不公平的行爲,因爲避免鎖車隊的原因。

有關鎖定車隊的更多信息,你應該在Designing Applications for High Performance閱讀裏克Vicik文章:

鎖定康宏

FIFO鎖保證公平,在 費用造成 向前進步鎖定車隊。術語 本意幾個線程 執行代碼的相同的部分 導致更高的碰撞 比如果它們在整個碼被隨機分佈 的基團(很像 汽車正在由交通燈分成分組 )。我說的 現象更糟 ,因爲一旦它形成隱含的 切換鎖擁有保持鎖步驟 線程。

舉例說明,請考慮示例 ,其中一個線程持有一個鎖,並且在持有該鎖的同時 被搶佔。 結果是所有其他線程 將堆積在該鎖的等待列表上。當搶佔線程(此時鎖具 擁有者)再次運行 並釋放鎖定時, 會自動將 鎖定的所有權移交到等待 列表上的第一個線程。該線程有時可能不運行 ,但「保持時間」時鐘 正在等待。以前的主人 通常要求鎖再次 之前的等待列表中清除出去, 延續車隊

+0

你是對的,它是靜態對象中的一個靜態對象,我寫得太快了。現在會解決它 – Matt 2009-08-25 20:51:09

0

Windows和CLR的嘗試,竭力爲保證公平等待的(先進先出順序)。但是,在某些情況下,等待鎖的線程順序可以更改,主要圍繞可警告等待進行,所有CLR線程鎖都將線程置於可警告狀態。

出於所有實際目的,您可以假定訂單將是FIFO;但是,請注意這個問題。

1

一個簡單的例子告訴我們,爲了不保證做到先進先出

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


namespace ConsoleApplication 
{ 
    class Program 
    { 
     private static Info info = new Info(); 

     static void Main(string[] args) 
     { 
      Thread[] t1 = new Thread[5]; 
      for (int i = 0; i < 5; i++) 
      { 
       t1[i] = new Thread(info.DoWork); 
      } 

      Thread[] t2 = new Thread[5]; 
      for (int i = 0; i < 5; i++) 
      { 
       t2[i] = new Thread(info.Process); 
      } 

      for (int i = 0; i < 5; i++) 
      { 
       t1[i].Start(); 
       t2[i].Start(); 
      } 

      Console.ReadKey(); 
     } 
    } 

    class Info 
    { 
     public object SynObject = new object(); 

     public void DoWork() 
     { 
      Debug.Print("DoWork Lock Reached: {0}", Thread.CurrentThread.ManagedThreadId); 
      lock (this.SynObject) 
      { 
       Debug.Print("Thread Lock Enter: {0}", Thread.CurrentThread.ManagedThreadId); 
       Thread.Sleep(5000); 
       Debug.Print("Thread Lock Exit: {0}", Thread.CurrentThread.ManagedThreadId); 
      } 
     } 

     public void Process() 
     { 
      Debug.Print("Process Lock Reached: {0}", Thread.CurrentThread.ManagedThreadId); 
      lock (this.SynObject) 
      { 
       Debug.Print("Process Lock Enter: {0}", Thread.CurrentThread.ManagedThreadId); 
       Thread.Sleep(5000); 
       Debug.Print("Process Lock Exit: {0}", Thread.CurrentThread.ManagedThreadId); 
      } 
     } 
    } 
} 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Diagnostics; 


namespace ConsoleApplication 
{ 
    class Program 
    { 
     private static Info info = new Info(); 

     static void Main(string[] args) 
     { 
      Thread[] t1 = new Thread[5]; 
      for (int i = 0; i < 5; i++) 
      { 
       t1[i] = new Thread(info.DoWork); 
      } 

      Thread[] t2 = new Thread[5]; 
      for (int i = 0; i < 5; i++) 
      { 
       t2[i] = new Thread(info.Process); 
      } 

      for (int i = 0; i < 5; i++) 
      { 
       t1[i].Start(); 
       t2[i].Start(); 
      } 

      Console.ReadKey(); 
     } 
    } 

    class Info 
    { 
     public object SynObject = new object(); 

     public void DoWork() 
     { 
      Debug.Print("DoWork Lock Reached: {0}", Thread.CurrentThread.ManagedThreadId); 
      lock (this.SynObject) 
      { 
       Debug.Print("Thread Lock Enter: {0}", Thread.CurrentThread.ManagedThreadId); 
       Thread.Sleep(5000); 
       Debug.Print("Thread Lock Exit: {0}", Thread.CurrentThread.ManagedThreadId); 
      } 
     } 

     public void Process() 
     { 
      Debug.Print("Process Lock Reached: {0}", Thread.CurrentThread.ManagedThreadId); 
      lock (this.SynObject) 
      { 
       Debug.Print("Process Lock Enter: {0}", Thread.CurrentThread.ManagedThreadId); 
       Thread.Sleep(5000); 
       Debug.Print("Process Lock Exit: {0}", Thread.CurrentThread.ManagedThreadId); 
      } 
     } 
    } 
} 

執行會PROCEDE這樣

Process Lock Reached: 15 
Process Lock Enter: 15 
DoWork Lock Reached: 12 
Process Lock Reached: 17 
DoWork Lock Reached: 11 
DoWork Lock Reached: 10 
DoWork Lock Reached: 13 
DoWork Lock Reached: 9 
Process Lock Reached: 18 
Process Lock Reached: 14 
Process Lock Reached: 16 
Process Lock Exit: 15 
Thread Lock Enter: 9 
Thread Lock Exit: 9 
Process Lock Enter: 14 
Process Lock Exit: 14 
Thread Lock Enter: 10 
Thread Lock Exit: 10 
Thread Lock Enter: 11 
Thread Lock Exit: 11 
Process Lock Enter: 16 
Process Lock Exit: 16 
Thread Lock Enter: 12 
Thread Lock Exit: 12 
Process Lock Enter: 17 
Process Lock Exit: 17 
Thread Lock Enter: 13 
Thread Lock Exit: 13 
Process Lock Enter: 18 
Process Lock Exit: 18 

東西正如你CA看到達到鎖的過程是鎖定不同輸入。