2011-11-03 8 views
6

件名にかなりの量の投稿を読みましたが、最終的にはvolatileというキーワードがC#でどのように機能するかを理解していると思います。それでも私はここで、コンセプトを正しく理解しているかどうかを確認したいと思っていました。別のスレッドがEnabled=falseを設定した場合、元のスレッドが実際にすぐにこの変更が表示されないことがあり、私が理解から.NETでスレッド間の一方向通信にvolatileを使用する

class ThreadWrapper 
{ 
    public bool Enabled { get; set; } 

    private void ThreadMethod() 
    { 
    while (Enabled) { // ... Do work } 
    } 
} 

次のコードを考えてみましょう(あるいは、これまで?)。コンパイラがEnabledプロパティへのアクセスを最適化せずにキャッシュされた値に依存しないようにするには、コードを次のように変更して修正する必要があります。

public bool Enabled { get {return mEnabled;} set {mEnabled=value;} } 
    private volatile bool mEnabled; 

有効値が読み取られるたびに、最新の値が正しいことが保証されていますか?もしそうなら、私は単純な信号やフラグとして使うことができるはずです(上記のように)。別の例として

、次の点を考慮してください。このような単純なスレッド間通信のために

class C 
{ 
    private volatile int i; 
    private volatile bool enabledA; 
    private volatile bool enabledB; 

    void ThreadA() 
    { 
    i = 0; // Reset counter 
    while (enabledA) 
    { 
     // .. Do some other repeated work 
     if (i > 100) 
     { 
     // .. Handle threshold case 
     } 
    } 
    } 

    void ThreadB() 
    { 
    while (enabledB) 
    { 
     // .. Do work 
     if (condition) // Some condition occurs that we want to count 
     { 
     i++; 
     } 
    } 
    } 
} 

を、ここで満足volatileのですか? i++はアトミックな操作ではありませんが、一方のスレッドがすべてインクリメントを行っていて、もう一方のスレッドが特定のしきい値に達しているかどうかを確認したい場合は、問題ありません。

編集:コースが見つかりましたanother similar question with detailed answersの後は事実です。

+1

私は、オブジェクト単位でフラグを立てる方法が必要な場合にvolatileを使用するのが大好きです。オブジェクトごとにロックを必要としません。例えば、バッチ処理を行う私のアプリケーションの中には、リスト内のオブジェクトで動作する複数のスレッドと、完了したときにオブジェクトに書き出すスレッドを持つものがあります。私は、ワーカースレッドが特定のオブジェクトで完了したときに揮発性の値を反転させ、ライタースレッドはスピン/スリープしてその値を待機し、リストを歩いているだけです。 – Bengie

答えて

3

はい、これは安全であり、volatileキーワードの用途の1つです。ただし、条件をテストするためにを単ににループしないでください。単に変更を待つ場合は、適切な同期プリミティブを使用してCPU時間を無駄にしないようにします。このテクニックは、スレッドを1つしか書いていないため動作しません。複数のスレッドがカウンタをインクリメントしようとすると、カウンタのヒットが失われる可能性があります(リード・モディファイ・ライトはアトミックではないためです)。

+0

私はこれが素晴らしい点だと思います。私が「揮発性」を集めることができるのは、実際には上記の私のような単純なケースにのみ役に立ちます。私は安全にマルチスレッドを行うのはかなりトリッキーな作業であることを学んでいます。 – Jeremy

関連する問題