2015-10-13 52 views
6

我要檢查一些鎖定行爲,我不明白這一點:鎖定在一個基本類型

static void Main(string[] args) 
{ 
    for (int i = 0; i < 10; i++) 
    { 
     Task.Factory.StartNew(() => 
     { 
      MultithreadedMethod(); 
     }); 
    } 

    Thread.Sleep(2000); 
    Console.WriteLine(count); 
} 

static int count = 0; 
private static readonly int sync = 5; 

public static void MultithreadedMethod() 
{ 
    if (Monitor.TryEnter(sync)) 
    { 
     count++; 
     Monitor.Exit(sync); 
    } 
} 

我認爲這不應該工作,由於我做的一個整數值同步。第一次拳擊,然後拆箱,我應該得到一個System.Threading.SynchronizationLockException,因爲缺少同步塊根(我知道這是特定於引用類型)。 我不會愚弄自己,即使這只是爲了迭代而工作,它並不是真正的同步..所以,考慮到增量操作的非原子屬性..我不會得到確定性的結果..我知道這個的。

事實上,當我擺脫那個Thead.Sleep,並把任務等待..異常到位。

Task.Factory.StartNew(() => 
{ 
     MultithreadedMethod(); 
}).Wait(); 

我覺得異常應該在這裏拋出:Monitor.Exit(sync)

但什麼抓住了嗎?

更新1:圖片已添加。

enter image description here

+0

當我運行上面的代碼時,它會從'Exit'引發異常。當然你從任務中捕獲異常? –

+0

@PatrickHofman這就是我擁有的一切。剛拍了照片。 –

回答

4

但是會發現什麼?

Task對象內部拋出的異常隱含在Task的內部。除非您在返回的任務上訪問Task.ExceptionTask.Wait/Task.Result屬性或await,否則該異常將被吞噬,您將無法看到它。這就是爲什麼使用Wait傳播異常,您可以在控制檯中看到它。如果您使用Task.WaitAll等待所有任務完成,則會發生同樣的情況。

如果不使用任何這些,你仍然可以通過註冊到TaskScheduler.UnobservedTaskException看到異常:

static void Main(string[] args) 
{ 
    TaskScheduler.UnobservedTaskException += (s,e) => Console.WriteLine(e.Exception); 

    for (int i = 0; i < 10; i++) 
    { 
     Task.Factory.StartNew(() => 
     { 
      MultithreadedMethod(); 
     }); 
    } 

    Thread.Sleep(2000); 
    Console.WriteLine(count); 
} 

產量:

Unobserved task exception

注意此代碼仍然有賽車中因爲我們實際上並沒有等待任何結果出現,這可能在2秒鐘的睡眠後不會發生。

+1

@thumbmunkeys即使在修復之後(感謝您指出了這一點),我們仍然存在競爭條件,所以它不會「真的」重要,但仍然會通過編輯來說清楚。 –

2

當我運行你的代碼,我看到在我的輸出窗口:

拋出異常: 'System.Threading.SynchronizationLockException' 在ConsoleApplication5.exe

我您猜測您沒有捕獲來自任務的異常(並且您的IDE在未處理時未設置爲中斷)。相反,睡眠線程的,試試這個:

List<Task> tasks = new List<Task>(); 
for (int i = 0; i < 21000; i++) 
{ 
    tasks.Add(Task.Factory.StartNew(() => 
    { 
     MultithreadedMethod(); 
    })); 
} 

Task.WaitAll(tasks.ToArray()); 

WaitAll將顯示異常。