2014-03-12 89 views
8

我一直在讀這本書從約瑟夫阿爾巴哈利約線程:
http://www.albahari.com/threading/爲什麼這個任務不是線程安全的?

在第2部分中,我發現這個例子:
http://www.albahari.com/threading/part2.aspx#_When_to_Lock

這裏是前述例子:

class ThreadUnsafe 
{ 
    static int _x; 
    static void Increment() { _x++; } 
    static void Assign() { _x = 123; } 
} 

線程安全版本:

class ThreadSafe 
{ 
    static readonly object _locker = new object(); 
    static int _x; 

    static void Increment() { lock (_locker) _x++; } 
    static void Assign() { lock (_locker) _x = 123; } 
} 

我不明白爲什麼指定方法不是線程安全的。 32位和64位架構上的整數賦值不應該是原子操作嗎?

回答

9

該任務是原子因爲任何閱讀線程將看到123或先前的值 - 不是一些中間值。但是,不能保證線程在看到兩個內存屏障之前將看到新的值:寫入線程中的寫入內存屏障和讀取線程中的讀取內存屏障。

如果你有兩個線程像這樣(做_x公開或內部,因此,它可以被讀取其他類型的課程後 - 反正,或在ThreadSafe類的代碼):

// Thread 1 
Console.WriteLine("Writing thread starting"); 
ThreadSafe.Assign(); 
Console.WriteLine("Writing thread done"); 


// Thread 2 
Console.WriteLine("Reading thread starting"); 
while (ThreadSafe._x != 123) 
{ 
    // Do nothing 
} 
Console.WriteLine("Reading thread done"); 

。 ..不能保證線程2永遠不會完成,因爲線程2可能不會「看到」線程1的任務。

+0

請問您能解釋一下while循環嗎?如果線程1始終將_ 123分配給_x,線程2還能從中讀取什麼? – Ivan

+0

添加了原始代碼,以澄清問題。 –

+0

@伊萬:那該怎麼辦?它只是試圖循環,直到線程2「看到」123到'_x'的賦值。關鍵是它可能永遠不會「看到」這種變化。 –

相關問題