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