2017-04-23 122 views
1
using System; 
using System.Threading; 

namespace Threading 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     Semaphore even = new Semaphore(1, 1); 
     Semaphore odd = new Semaphore(1, 1); 

     Thread evenThread = new Thread(() => 
     { 
      for (int i = 1; i <= 100; i++) 
      { 
       even.WaitOne(); 
       if(i % 2 == 0) 
       { 
        Console.WriteLine(i); 
       } 
       odd.Release(); 
      } 
     }); 

     Thread oddThread = new Thread(() => 
     { 
      for(int i = 1; i <=100; i++) 
      { 
       odd.WaitOne(); 
       if(i%2 != 0) 
       { 
        Console.WriteLine(i); 
       } 
       even.Release(); 
      } 
     }); 


     oddThread.Start(); 
     evenThread.Start(); 
    } 


} 
} 

所以我寫了這個代碼,其中一個線程正在生成奇數並且其他正在生成偶數。此代碼是否會導致死鎖?

使用Semaphores我確信他們在訂單中打印數字並且完美地工作。

但我有一個特殊的情況,例如每個線程一直等到另一個線程釋放它的信號。那麼是否會出現這樣一種情況,即兩個線程都在等待,並且沒有線程正在取得進展,並且存在死鎖情況?

+0

錯誤地初始化信號將很容易做到。請注意,你做錯了,你創建了一個競爭條件,兩個線程都會同時嘗試WriteLine()。理想情況下,它會崩潰,因爲你在一個沒有等待但不會經常發生的信號量上調用Release。但不,沒有僵局。 System.Threading.Barrier類可以做到這一點,當你不必重新創建它時總會更好。 –

回答

1

要發生死鎖,兩個或更多線程必須嘗試獲取兩個或更多資源,但以不同的順序執行。見例如DeadlockWould you explain lock ordering?

你的代碼不會涉及每個線程多個鎖所以不具備死鎖的能力。

確實有能力引發異常。正如在this comment中指出的那樣,從理論上講,其中一個線程在其他線程之前足夠遠以至於它試圖釋放尚未被佔用的信號量鎖。例如,如果evenThread在第一次調用even.WaitOne()之前被預先佔用(或者根本沒有計劃開始運行),但oddThread可以運行,則oddThread可以獲取odd信號量,處理if語句,然後在evenThread有機會獲得該信號燈之前嘗試呼叫even.Release()

這將導致被撥打給Release()

這對於單CPU系統來說可能性更大,這是目前很難找到的。 :)但是對於任何CPU配置,理論上它仍然是可能的。


†實際上,在設計中線程安全的Console.WriteLine()調用中存在隱式鎖定。但是從你的代碼的角度來看,這是一個原子操作。你的代碼不可能獲得該鎖,然後等待另一個鎖。所以它與你的具體問題沒有任何關係。

相關問題