2012-11-13 37 views
10

これはちょっと夢中に思えるかもしれませんが、奇妙な振る舞いを引き起こさないことが合理的に確信できれば、私は大きなライブラリの一部として考えています。マルチスレッドC#5.0のスレッドプール上での非同期 - スレッドセーフ?

アプローチ:スレッドプールに派遣SynchronizationContext

実行非同期ユーザーコード。私はsomeStateへのアクセスは、スレッドセーフであるかどうかは確かではないよ

async void DoSomething() 
{ 
    int someState = 2; 
    await DoSomethingAsync(); 
    someState = 4; 
    await DoSomethingElseAsync(); 
    // someState guaranteed to be 4? 
} 

:ユーザコードは次のようになります。実際には、操作が完全に順序付けされるように、コードは1つの「スレッド」内で実行されますが、フードの下の複数のスレッドに分割される可能性があります。私の理解が正しいならば、順序はx86で安全でなければならず、変数が共有されていないので、コンパイラの最適化などを心配する必要はありません。

さらに重要なことに、私は、これがECMAまたはCLRメモリモデルでスレッドセーフであるかどうかについて懸念しています。

私は、キューに入れられた作業を実行する前にメモリバリアを挿入する必要があるとは確信していますが、ここでの私の推論には完全に自信がありません(または、このアプローチはまったく別の理由で実行できないかもしれません) 。

+5

これはローカル変数です。どのようにスレッドセーフではないのですか?私はあなたがそれが別のスレッドで変更することができると思いますか? (表示されていない参照(つまり、 'ref'またはキャプチャされた変数)を渡している場合を除きます。 – leppie

+3

私が理解しているところから、 'await'は次のコードを、' Task'が終了したときに現在の 'SynchronizationContext'で実行される継続に変換します。これがスレッドプールにディスパッチされている場合、継続は別のスレッドで実行できます。どのような方法でも*同時に実行することはありませんが、継続が別の物理スレッドで実行されている場合、 'someState'の変更が確実に見えるかどうかはわかりません。 – ShZ

+2

これは大きな質問です。多くの人が尋ねることさえ知りません。 –

答えて

9

これはasync/await FAQのコメント欄に回答される:

TPLは、値が適切に可視化されるように、タスクがキューに入れられ、タスク実行の開始/終了にある適切な障壁を含みます。

したがって、明示的な障壁は必要ありません。

関連する問題