1 回答

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超13個(gè)贊
有幾件事:
您的
Update()
方法將寫入同步到屬性MyValue
,但對(duì)讀取不執(zhí)行任何操作。因此,運(yùn)行時(shí)可以自由地使用對(duì)象的緩存值。這不太可能與您觀察到的輸出有任何關(guān)系,因?yàn)閷?shí)際上您不太可能看到這一點(diǎn),尤其是在 x86 硬件上。但…更重要的是,您的代碼所展示的只是輸出順序可能會(huì)產(chǎn)生誤導(dǎo)。該類
Console
具有同步功能以確保來(lái)自多個(gè)線程的一致輸出,但是代碼中沒(méi)有任何內(nèi)容可以確保如果按特定順序?qū)懭胼敵鲂?,則導(dǎo)致這些輸出行的代碼(例如讀取屬性)MyValue
發(fā)生與這些輸出行的顯示順序相同。
換句話說(shuō),僅僅因?yàn)?em>控制臺(tái)"2:"
在該行之前顯示了該行"3:"
,實(shí)際上并不意味著對(duì)的調(diào)用發(fā)生Update("Thread1")
在對(duì)Console.WriteLine("3: " + obj.MyValue);
lock
如果您想確保輸出行與程序中語(yǔ)句的執(zhí)行順序相匹配,您還需要使用語(yǔ)句來(lái)保護(hù)各個(gè)操作。
更具體地說(shuō),請(qǐng)考慮以下可能的代碼執(zhí)行順序:
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()即,在第一個(gè)線程開(kāi)始其邏輯之前,第二個(gè)線程計(jì)算傳遞給的參數(shù)是完全合法的。但是,第一個(gè)線程也可以在第二個(gè)線程有機(jī)會(huì)實(shí)際調(diào)用該Console.WriteLine()方法之前搶占第二個(gè)線程。
如果發(fā)生這種情況,您會(huì)看到線程 1 的預(yù)期輸出順序,但線程 2 的輸出寫入該屬性的明顯過(guò)時(shí)版本MyValue,因?yàn)樗窃诰€程 1 運(yùn)行其任何邏輯之前檢索到的。
為了解決該特定場(chǎng)景,您可以使用lock呼叫WriteLine()。例如:
lock (MyObject) Console.WriteLine("1: " + obj.MyValue);
請(qǐng)注意,您需要將其放在每次調(diào)用Console.WriteLine(). 這將確保寫入控制臺(tái)的任何值都是調(diào)用時(shí)屬性的最新值。
- 1 回答
- 0 關(guān)注
- 125 瀏覽
添加回答
舉報(bào)