10
這看起來可能有些瘋狂,但如果我可以合理地確定它不會造成奇怪的行爲,那麼這是一種我正在考慮作爲大型圖書館一部分的方法。在線程池中複用C#5.0的異步 - 線程安全嗎?
的方法:
運行異步用戶與SynchronizationContext
是分派給一個線程池的代碼。用戶代碼看起來是這樣的:
async void DoSomething()
{
int someState = 2;
await DoSomethingAsync();
someState = 4;
await DoSomethingElseAsync();
// someState guaranteed to be 4?
}
我不能肯定獲得someState
是否是線程安全的。雖然代碼可以在一個「線程」中運行,事實上,這些操作是完全有序的,但它仍然可以在引擎蓋下面的多個線程中分割。如果我的理解是正確的,在x86上的順序應該是安全的,並且由於該變量不被共享,所以我不需要擔心編譯器優化等問題。
更重要的是,我擔心在ECMA或CLR內存模型下這是否會保證線程安全。我很確定我需要在執行排隊工作之前插入內存屏障,但是我對這裏的推理並不完全有信心(或者這種方法可能因爲完全不同的原因而不可行) 。
這是一個局部變量。它怎麼能不是線程安全的? IOW是什麼讓你認爲它可以在另一個線程中被改變? (除非你將某個引用傳遞給某個不顯示的地方,即'ref'或者一個被捕獲的變量)。 – leppie
根據我的理解,'await'將下面的代碼轉換成繼承,當底層的'Task'完成時,它將在當前的'SynchronizationContext'上執行。如果這是調度到線程池,那麼延續可以運行在不同的線程上。它不會以任何方式同時運行*,但我不確定如果延續在另一個物理線程上執行,是否可以保證「someState」的更改可見。 – ShZ
這是一個很好的問題,很多人甚至不知道要問。 –