1 回答

TA貢獻1828條經驗 獲得超13個贊
有幾件事:
您的
Update()
方法將寫入同步到屬性MyValue
,但對讀取不執行任何操作。因此,運行時可以自由地使用對象的緩存值。這不太可能與您觀察到的輸出有任何關系,因為實際上您不太可能看到這一點,尤其是在 x86 硬件上。但…更重要的是,您的代碼所展示的只是輸出順序可能會產生誤導。該類
Console
具有同步功能以確保來自多個線程的一致輸出,但是代碼中沒有任何內容可以確保如果按特定順序寫入輸出行,則導致這些輸出行的代碼(例如讀取屬性)MyValue
發生與這些輸出行的顯示順序相同。
換句話說,僅僅因為控制臺"2:"
在該行之前顯示了該行"3:"
,實際上并不意味著對的調用發生Update("Thread1")
在對Console.WriteLine("3: " + obj.MyValue);
lock
如果您想確保輸出行與程序中語句的執行順序相匹配,您還需要使用語句來保護各個操作。
更具體地說,請考慮以下可能的代碼執行順序:
thread 1 thread 2
-------- --------
"value" parameter <= "3: " + obj.MyValue
Console.WriteLine("1: " + obj.MyValue);
Update("Thread1");
Console.WriteLine("2: " + obj.MyValue);
Console.WriteLine(value);
Console.WriteLine()即,在第一個線程開始其邏輯之前,第二個線程計算傳遞給的參數是完全合法的。但是,第一個線程也可以在第二個線程有機會實際調用該Console.WriteLine()方法之前搶占第二個線程。
如果發生這種情況,您會看到線程 1 的預期輸出順序,但線程 2 的輸出寫入該屬性的明顯過時版本MyValue,因為它是在線程 1 運行其任何邏輯之前檢索到的。
為了解決該特定場景,您可以使用lock呼叫WriteLine()。例如:
lock (MyObject) Console.WriteLine("1: " + obj.MyValue);
請注意,您需要將其放在每次調用Console.WriteLine(). 這將確保寫入控制臺的任何值都是調用時屬性的最新值。
- 1 回答
- 0 關注
- 118 瀏覽
添加回答
舉報