Is accessing a bool field atomic in C#? In particular, do I need to put a lock around:
class Foo
{
private bool _bar;
//... in some function on any thread (or many threads)
_bar = true;
//... same for a read
if (_bar) { ... }
}
Is accessing a bool field atomic in C#? In particular, do I need to put a lock around:
class Foo
{
private bool _bar;
//... in some function on any thread (or many threads)
_bar = true;
//... same for a read
if (_bar) { ... }
}
Yes.
Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types.
as found in C# Language Spec.
Edit: It's probably also worthwhile understanding the volatile keyword.
_bar = true;
at least once, not using volatile at worst means that the if statement won't be take temporarily even though _bar is true. I'd suggest to just use locks if precision is required. –
Bostwick if
shouldn't be entered until a thread has set _bar = true;
, then volatile is exactly what you want - why would you need locks here? –
Distressed Interlocked.Add(ref myInt);
e.g.? –
Nuremberg i++
is equal to i=i+1
, meaning you do an atomic read, then addition, then atomic write. Another thread could modify i
after the read but before the write. For example two threads doing i++
concurrently on the same i can happen to read at the same time (and thus read the same value), add one to it and then both write the same value, effectively adding only once. Interlocked.Add prevents this. As a general rule the fact that a type is atomic is only useful if there's only one thread writing but many threads reading. –
Presignify volatile
keyword is wrong with regarding to synchronization problems as volatile
alone does not put memory barrier. –
Hau As stated above, bool
is atomic, but you still need to remember that it also depends on what you want to do with it.
if(b == false)
{
//do something
}
is not an atomic operation, meaning that the value of b
could change before the current thread executes the code after the if
statement.
bool accesses are indeed atomic, but that isn't the whole story.
You don't have to worry about reading a value that is 'incompletely written' - it isn't clear what that could possibly mean for a bool in any case - but you do have to worry about processor caches, at least if details of timing are an issue. If thread #1 running on core A has your _bar
in cache, and _bar
gets updated by thread #2 running on another core, thread #1 will not see the change immediately unless you add locking, declare _bar
as volatile
, or explicitly insert calls to Thread.MemoryBarrier()
to invalidate the cached value.
var fatObject = new FatObject(); Thread.MemoryBarrier(); _sharedRefToFat = fatObject;
–
Kamacite the approach I have used, and I think is correct, is
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;
}
}
}
the goal was basically to avoid having to repetively lock an object on every iteration just to check if we needed to lock it in order to provide a large amount of state change information which occurs rarely. I think this approach works. And if absolute consistancy is required, I think volatile would be appropriate on the b bool.
lock()
, you do not need volatile
. –
Panache © 2022 - 2024 — McMap. All rights reserved.