Does Boolean not need an Interlocked.Exchange method?
-
There appears to be no way to use Threading.Interlocked methods to change the value of a boolean. There's Increment and Decrement for Ints, and Exchange for reference types, but nothing for changing the value of a boolean in a thread-safe manner. Is this not required? Are changes to booleans already threadsafe?
-
There appears to be no way to use Threading.Interlocked methods to change the value of a boolean. There's Increment and Decrement for Ints, and Exchange for reference types, but nothing for changing the value of a boolean in a thread-safe manner. Is this not required? Are changes to booleans already threadsafe?
JoeRip wrote:
Are changes to booleans already threadsafe?
Half the time, they are :P Don't you just put a lock block over the code where you change it ?
Christian Graus No longer a Microsoft MVP, but still happy to answer your questions.
-
JoeRip wrote:
Are changes to booleans already threadsafe?
Half the time, they are :P Don't you just put a lock block over the code where you change it ?
Christian Graus No longer a Microsoft MVP, but still happy to answer your questions.
You mean, have a lock object for every private field in my class? Or have a single lock object that I lock every time I change any private field in my class? The first seems excessive, and the second seems... anti-performant. I thought the Interlocked methods WERE tiny little lock blocks, used in an atomic fashion.... Or am I missing something fundamental here?
-
You mean, have a lock object for every private field in my class? Or have a single lock object that I lock every time I change any private field in my class? The first seems excessive, and the second seems... anti-performant. I thought the Interlocked methods WERE tiny little lock blocks, used in an atomic fashion.... Or am I missing something fundamental here?
Declare it as volatile. :P
Mark Churchill Director, Dunn & Churchill Pty Ltd Free Download: Diamond Binding: The simple, powerful, reliable, and effective data layer toolkit for Visual Studio.
Alpha release: Entanglar: Transparant multiplayer framework for .Net games. -
Declare it as volatile. :P
Mark Churchill Director, Dunn & Churchill Pty Ltd Free Download: Diamond Binding: The simple, powerful, reliable, and effective data layer toolkit for Visual Studio.
Alpha release: Entanglar: Transparant multiplayer framework for .Net games. -
I didn't know there were interlock methods, I'd always just create an object in the same scope as the variable and do lock(myLockingObject) { theBool = false; }
Christian Graus No longer a Microsoft MVP, but still happy to answer your questions.
-
Declare it as volatile. :P
Mark Churchill Director, Dunn & Churchill Pty Ltd Free Download: Diamond Binding: The simple, powerful, reliable, and effective data layer toolkit for Visual Studio.
Alpha release: Entanglar: Transparant multiplayer framework for .Net games.Mark Churchill wrote:
Declare it as volatile
I am not sure, but I think volatile doesn't make the type thread safe. It only allows to read the latest value written by other threads.
All C# applications should call Application.Quit(); in the beginning to avoid any .NET problems.- Unclyclopedia How to use google | Ask smart questions
-
There appears to be no way to use Threading.Interlocked methods to change the value of a boolean. There's Increment and Decrement for Ints, and Exchange for reference types, but nothing for changing the value of a boolean in a thread-safe manner. Is this not required? Are changes to booleans already threadsafe?
Access to all primitive types <=32 bit is atomic. So reading and writing ints and bools is safe. But a "read-modify-write" operation is not atomic; so for integers, there's Interlocked.Increment etc. Now, the only kind of "read-modify-write" I could image for bools is negating them. That's not safe. But something like "if (!a) { a = true; }" is safe: if another thread happens to change the value between the "if (!a)" and the "a = true;", the only thing it can have done is setting a to true - but that's not going cause any problems, since we are about to set a to true anyway. However, if you use the boolean for things like "run this code only once", then you have to lock/use Interlocked.CompareExchange to ensure that only the first thread to set the boolean to true runs the "run only once" code. Remember that usually, there's no point in making all members of a class thread-safe, as combined operations need locking anyways, so the user of a class usually has to do his own locking. E.g. given a thread-safe list, "if (!list.Contains(x)) list.Add(x);" is not thread-safe, so you need to "lock (list)" around every list access - but if you have to lock around every access, you could as well start with a non-thread-safe list.
-
Access to all primitive types <=32 bit is atomic. So reading and writing ints and bools is safe. But a "read-modify-write" operation is not atomic; so for integers, there's Interlocked.Increment etc. Now, the only kind of "read-modify-write" I could image for bools is negating them. That's not safe. But something like "if (!a) { a = true; }" is safe: if another thread happens to change the value between the "if (!a)" and the "a = true;", the only thing it can have done is setting a to true - but that's not going cause any problems, since we are about to set a to true anyway. However, if you use the boolean for things like "run this code only once", then you have to lock/use Interlocked.CompareExchange to ensure that only the first thread to set the boolean to true runs the "run only once" code. Remember that usually, there's no point in making all members of a class thread-safe, as combined operations need locking anyways, so the user of a class usually has to do his own locking. E.g. given a thread-safe list, "if (!list.Contains(x)) list.Add(x);" is not thread-safe, so you need to "lock (list)" around every list access - but if you have to lock around every access, you could as well start with a non-thread-safe list.
Daniel Grunwald wrote:
However, if you use the boolean for things like "run this code only once", then you have to lock/use Interlocked.CompareExchange to ensure that only the first thread to set the boolean to true runs the "run only once" code.
Remember that there is no Interlocked.CompareExchange for boolean types. You can use an INT and treat it like a boolean, but that's pretty inelegant. Oddly enough, Microsoft has repeatedly chosen not to support booleans in the Interlocked methods, despite the many requests I found in their forums/Connection Feedbacks.
-
Daniel Grunwald wrote:
However, if you use the boolean for things like "run this code only once", then you have to lock/use Interlocked.CompareExchange to ensure that only the first thread to set the boolean to true runs the "run only once" code.
Remember that there is no Interlocked.CompareExchange for boolean types. You can use an INT and treat it like a boolean, but that's pretty inelegant. Oddly enough, Microsoft has repeatedly chosen not to support booleans in the Interlocked methods, despite the many requests I found in their forums/Connection Feedbacks.
JoeRip wrote:
You can use an INT and treat it like a boolean, but that's pretty inelegant.
That's what I do. If you need interlocked booleans frequently, create a custom bool type to make the calling code a bit more elegant:
public struct MyBoolean
{
public static readonly MyBoolean False = new MyBoolean(0);
public static readonly MyBoolean True = new MyBoolean(1);int val; private MyBoolean(int val) { this.val = val; } public MyBoolean CompareExchange(MyBoolean value, MyBoolean comparand) { return new MyBoolean(Interlocked.CompareExchange(ref val, value.val, comparand.val)); } public static implicit bool(MyBoolean a) { return a.val != 0; } public static implicit MyBoolean(bool a) { return a ? True : False; } public static bool operator ==(MyBoolean a, MyBoolean b) { return a.val == b.val; } // and the other operators...
}
-
Mark Churchill wrote:
Declare it as volatile
I am not sure, but I think volatile doesn't make the type thread safe. It only allows to read the latest value written by other threads.
All C# applications should call Application.Quit(); in the beginning to avoid any .NET problems.- Unclyclopedia How to use google | Ask smart questions
"...all threads will observe volatile writes performed by any other thread in the order in which they were performed." See http://msdn.microsoft.com/en-us/library/aa645755(VS.71).aspx[^]
Mark Churchill Director, Dunn & Churchill Pty Ltd Free Download: Diamond Binding: The simple, powerful, reliable, and effective data layer toolkit for Visual Studio.
Alpha release: Entanglar: Transparant multiplayer framework for .Net games.