C#でboolフィールドにアクセスしていますか?特に、ロックをかける必要がありますか?
class Foo
{
private bool _bar;
//... in some function on any thread (or many threads)
_bar = true;
//... same for a read
if (_bar) { ... }
}
C#でboolフィールドにアクセスしていますか?特に、ロックをかける必要がありますか?
class Foo
{
private bool _bar;
//... in some function on any thread (or many threads)
_bar = true;
//... same for a read
if (_bar) { ... }
}
回答:
Interlocked.Add(ref myInt);
たとえば?
i++
はに等しいi=i+1
。つまり、アトミック読み取り、加算、アトミック書き込みの順に実行します。別のスレッドはi
、読み取り後、書き込み前に変更される可能性があります。たとえばi++
、同じiで同時に実行している2つのスレッドは、たまたま同時に読み取り(したがって、同じ値を読み取り)、1つを追加してから、両方が同じ値を書き込み、事実上1回だけ追加する可能性があります。Interlocked.Addはこれを防ぎます。原則として、型がアトミックであるという事実は、書き込みスレッドが1つだけで、読み取りスレッドが多い場合にのみ役立ちます。
上で述べたように、boolはアトミックですが、それを使用して何をしたいかにも依存することを覚えておく必要があります。
if(b == false)
{
//do something
}
はアトミック操作ではありません。つまり、現在のスレッドがifステートメントの後にコードを実行する前にb値が変更される可能性があります。
ブールアクセスは確かにアトミックですが、それだけではありません。
「不完全に書き込まれた」値の読み取りについて心配する必要はありません-いずれにせよ、それがブール値にとって何を意味するのかは明確ではありません-しかし、少なくとも次の詳細については、プロセッサキャッシュについて心配する必要があります。タイミングが問題です。コアAで実行されているスレッド#1_bar
にキャッシュがあり、_bar
別のコアで実行されているスレッド#2によって更新された場合、ロックを追加するか、_bar
として宣言するvolatile
か、明示的に呼び出しを挿入しThread.MemoryBarrier()
て無効にしない限り、スレッド#1はすぐに変更を確認しません。キャッシュされた値。
var fatObject = new FatObject(); Thread.MemoryBarrier(); _sharedRefToFat = fatObject;
私が使用したアプローチは正しいと思いますが、
volatile bool b = false;
.. rarely signal an update with a large state change...
lock b_lock
{
b = true;
//other;
}
... another thread ...
if(b)
{
lock b_lock
{
if(b)
{
//other stuff
b = false;
}
}
}
目標は基本的に、めったに発生しない大量の状態変更情報を提供するためにオブジェクトをロックする必要があるかどうかを確認するために、反復ごとにオブジェクトを繰り返しロックする必要がないようにすることでした。私が考えるこのアプローチは動作します。そして、絶対的な一貫性が必要な場合は、bboolでvolatileが適切だと思います。
lock()
、あなたは必要ありませんvolatile
。