I'm just wondering whether this code that a fellow developer (who has since left) is OK, I think he wanted to avoid putting a lock. Is there a performance difference between this and just using a straight forward lock?
private long m_LayoutSuspended = 0;
public void SuspendLayout()
{
Interlocked.Exchange(ref m_LayoutSuspended, 1);
}
public void ResumeLayout()
{
Interlocked.Exchange(ref m_LayoutSuspended, 0);
}
public bool IsLayoutSuspended
{
get { return Interlocked.Read(ref m_LayoutSuspended) != 1; }
}
I was thinking that something like that would be easier with a lock? It will indeed be used by multiple threads, hence why the use of locking/interlocked was decided.
Yes what you are doing is safe from a race point of view reaching the m_LayoutSuspended field, however, a lock is required for the following reason if the code does the following:
if (!o.IsLayoutSuspended) // This is not thread Safe .....
{
o.SuspendLayout(); // This is not thread Safe, because there's a difference between the checck and the actual write of the variable a race might occur.
...
o.ResumeLayout();
}
A safer way, that uses CompareExchange to make sure no race conditions have occurred:
private long m_LayoutSuspended = 0;
public bool SuspendLayout()
{
return Interlocked.CompareExchange(ref m_LayoutSuspended, 1) == 0;
}
if (o.SuspendLayout())
{
....
o.ResumeLayout();
}
Or better yet simply use a lock.
Personally I'd use a volatile Boolean:
private volatile bool m_LayoutSuspended = false;
public void SuspendLayout()
{
m_LayoutSuspended = true;
}
public void ResumeLayout()
{
m_LayoutSuspended = false;
}
public bool IsLayoutSuspended
{
get { return m_LayoutSuspended; }
}
Then again, as I've recently acknowledged elsewhere, volatile doesn't mean quite what I thought it did. I suspect this is okay though :)
Even if you stick with Interlocked, I'd change it to an int... there's no need to make 32 bit systems potentially struggle to make a 64 bit write atomic when they can do it easily with 32 bits...
Related
I want to know, if trying to update a boolean value being used by a thread is guaranteed to be successful, without any lock protection.
like the following case:
there wont be any problem for Stop() to change the boolean member of m_ThreadActive, while threadproc is running?
private bool m_ThreadActive = true;
public void threadproc
{
while (m_ThreadActive)
{
...
}
}
public void Stop()
{
m_ThreadActive = false;
}
It is theoretically possible that the compiler could optimise the loop in such a way that the loop variable always remains true.
To ensure that can't happen, use a Volatile.Read():
while (Volatile.Read(ref ThreadActive))
If you don't have a version of .Net which supports Volatile.Read() you could declare m_ThreadActive as volatile:
private volatile bool m_ThreadActive = true;
Or, better, use Thread.MemoryBarrier():
while (ThreadActive)
{
Thread.MemoryBarrier();
// ...
}
See my answer here for a program that demonstrates a requirement for volatile, Volatile.Read() or Thread.MemoryBarrier() for it to work correctly.
For more information on why the use of the volatile keyword can be a bit suspect, see this article from Eric Lippert.
Just checking... _count is being accessed safely, right?
Both methods are accessed by multiple threads.
private int _count;
public void CheckForWork() {
if (_count >= MAXIMUM) return;
Interlocked.Increment(ref _count);
Task t = Task.Run(() => Work());
t.ContinueWith(CompletedWorkHandler);
}
public void CompletedWorkHandler(Task completedTask) {
Interlocked.Decrement(ref _count);
// Handle errors, etc...
}
This is thread safe, right?
Suppose MAXIMUM is one, count is zero, and five threads call CheckForWork.
All five threads could verify that count is less than MAXIMUM. The counter would then be bumped up to five and five jobs would start.
That seems contrary to the intention of the code.
Moreover: the field is not volatile. So what mechanism guarantees that any thread will read an up-to-date value on the no-memory-barrier path? Nothing guarantees that! You only make a memory barrier if the condition is false.
More generally: you are making a false economy here. By going with a low-lock solution you are saving the dozen nanoseconds that the uncontended lock would take. Just take the lock. You can afford the extra dozen nanoseconds.
And even more generally: do not write low-lock code unless you are an expert on processor architectures and know all optimizations that a CPU is permitted to perform on low-lock paths. You are not such an expert. I am not either. That's why I don't write low-lock code.
No, if (_count >= MAXIMUM) return; is not thread safe.
edit: You'd have to lock around the read too, which should then logically be grouped with the increment, so I'd rewrite like
private int _count;
private readonly Object _locker_ = new Object();
public void CheckForWork() {
lock(_locker_)
{
if (_count >= MAXIMUM)
return;
_count++;
}
Task.Run(() => Work());
}
public void CompletedWorkHandler() {
lock(_locker_)
{
_count--;
}
...
}
That's what Semaphore and SemaphoreSlim are for:
private readonly SemaphoreSlim WorkSem = new SemaphoreSlim(Maximum);
public void CheckForWork() {
if (!WorkSem.Wait(0)) return;
Task.Run(() => Work());
}
public void CompletedWorkHandler() {
WorkSem.Release();
...
}
No, what you have is not safe. The check to see if _count >= MAXIMUM could race with the call to Interlocked.Increment from another thread. This is actually really hard to solve using low-lock techniques. To get this to work properly you need to make a series of several operations appear atomic without using a lock. That is the hard part. The series of operations in question here are:
Read _count
Test _count >= MAXIMUM
Make a decision based on the above.
Increment _count depending on the decision made.
If you do not make all 4 of these steps appear atomic then there will be a race condition. The standard pattern for performing a complex operation without taking a lock is as follows.
public static T InterlockedOperation<T>(ref T location)
{
T initial, computed;
do
{
initial = location;
computed = op(initial); // where op() represents the operation
}
while (Interlocked.CompareExchange(ref location, computed, initial) != initial);
return computed;
}
Notice what is happening. The operation is repeatedly performed until the ICX operation determines that the initial value has not changed between the time it was first read and the time the attempt was made to change it. This is the standard pattern and the magic all happens because of the CompareExchange (ICX) call. Note, however, that this does not take into account the ABA problem.1
What you could do:
So taking the above pattern and incorporating it into your code would result in this.
public void CheckForWork()
{
int initial, computed;
do
{
initial = _count;
computed = initial < MAXIMUM ? initial + 1 : initial;
}
while (Interlocked.CompareExchange(ref _count, computed, initial) != initial);
if (replacement > initial)
{
Task.Run(() => Work());
}
}
Personally, I would punt on the low-lock strategy entirely. There are several problems with what I presented above.
This might actually run slower than taking a hard lock. The reasons are difficult to explain and outside the scope of my answer.
Any deviation from what is above will likely cause the code to fail. Yes, it really is that brittle.
It is hard to understand. I mean look at it. It is ugly.
What you should do:
Going with the hard lock route your code might look like this.
private object _lock = new object();
private int _count;
public void CheckForWork()
{
lock (_lock)
{
if (_count >= MAXIMUM) return;
_count++;
}
Task.Run(() => Work());
}
public void CompletedWorkHandler()
{
lock (_lock)
{
_count--;
}
}
Notice that this is much simpler and considerably less error prone. You may actually find that this approach (hard lock) is actually faster than what I showed above (low lock). Again, the reason is tricky and there are techniques that can be used to speed things up, but it outside the scope of this answer.
1The ABA problem is not really an issue in this case because the logic does not depend on _count remaining unchanged. It only matters that its value is the same at two points in time regardless of what happened in between. In other words the problem can be reduced to one in which it seemed like the value did not change even though in reality it may have.
Define thread safe.
If you want to ensure that _count will never be greater than MAXIMUM, than you did not succeed.
What you should do is lock around that too:
private int _count;
private object locker = new object();
public void CheckForWork()
{
lock(locker)
{
if (_count >= MAXIMUM) return;
_count++;
}
Task.Run(() => Work());
}
public void CompletedWorkHandler()
{
lock(locker)
{
_count--;
}
...
}
You might also want to take a look at The SemaphoreSlim class.
you can do the following if you don't want to lock or move to a semaphore:
if (_count >= MAXIMUM) return; // not necessary but handy as early return
if(Interlocked.Increment(ref _count)>=MAXIMUM+1)
{
Interlocked.Decrement(ref _count);//restore old value
return;
}
Task.Run(() => Work());
Increment returns the incremented value on which you can double check whether _count was less than maximum, if the test fails then I restore the old value
In my project there is an audio thread updating with about 86 fps and a graphics thread which runs at 60 fps. Both threads can produce and consume values from each other.
But it is not necessary to consume every value, only the latest one is important and no notification is required because the threads just ask for a new value when they need one.
After reading tons of websites about threading I am a bit confused what I really need, because my task is quite simple. With locks my code would look like:
private T aField; //memory location
//other thread reads value
public void ReadValue(ref T val)
{
lock(myLock) copy aField to val;
}
//this thread updates value
private void UpdateValue(T newVal)
{
lock(myLock) copy newVal to aField;
}
My first question is, would this work for primitive types like float or int (<=32bit of size) without any lock because the copy is only one assignment which is atomic?
The next idea was a protection by a bool:
private T aField; //memory location
private volatile bool isReading;
private volatile bool isWriting;
//other thread reads value
public void ReadValue(ref T val)
{
isReading = true;
if(!isWriting) copy aField to val;
isReading = false;
}
//this thread updates value
private void UpdateValue(T newVal)
{
isWriting = true;
if(!isReading) copy newVal to aField;
isWriting = false;
}
Looks good to me but i am pretty sure i missed something. I could think of a worst case scenario when the faster thread reads while the slow thread wants to write. then the fast thread will read again the older value the next time, because no update was done.
What i also found was a nonblocking update method, but i wonder if and how it can help me:
static void LockFreeUpdate<T> (ref T field, Func <T, T> updateFunction)
where T : class
{
var spinWait = new SpinWait();
while (true)
{
T snapshot1 = field;
T calc = updateFunction (snapshot1);
T snapshot2 = Interlocked.CompareExchange (ref field, calc, snapshot1);
if (snapshot1 == snapshot2) return;
spinWait.SpinOnce();
}
}
What is the most efficient method with the lowest latency?
for your case you do not need any locks, just add volatile to private T aField; to prevent any possible compiler optimizations
I have a class that talks to an external .exe. The class has a bunch of similar methods; they call a function of the .exe, wait for response, and then return true or false.
The response comes in the form of events that change the values of fields of this class.
Simplified code:
class Manager
{
private static bool connected = false;
public static bool Connect()
{
runtime.Connect();
int secondsWaited = 0;
while (!connected)
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}
return true;
}
}
The other methods use the same call-wait-loop-return structure.
My goal is to make a single method to do this waiting for me, like so:
private static bool WaitReferenceEqualsValue<T>(ref T reference, T value)
{
int secondsWaited = 0;
while (!reference.Equals(value))
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}
return true;
}
Then each method would do:
runtime.DoSomething();
return WaitReferenceEqualsValue<someType>(ref someField, someSuccessfulValue);
However, when I replace the wait-loop with this method call, the field "connected", even though passed in as a reference, always stays the same.
Any idea what's going on here, and how to get the desired functionality?
Thanks in advance.
EDIT:
public static bool Connect()
{
...
runtime.Connect();
// this code works
/*int secondsWaited = 0;
while (connected != true)
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}*/
// this somehow blocks OnConnect from firing, so connected never gets set to true
lock (typeof(SkypeKitManager))
{
WaitReferenceEqualsValue<bool>(ref connected, true);
}
...
}
OnConnect:
private static void OnConnect(object sender, Events.OnConnectArgs e)
{
if (e != null && e.success)
{
lock (typeof(Manager))
{
connected = true;
}
}
}
You're not doing any synchronization on that field although you access it from multiple threads and one of them is writing. This is a race (no exception! this is a race even if it looks safe. It isn't safe.).
Probably the JIT enregistered it which is a common optimization. It just never gets read from memory, always from a register. Add synchronization (for example a lock, or Interlocked or Volatile methods).
Your usage of ref is correct.
The problem with your code is essentially compiler optimization. Fo optimization purpose compilers (or jits) necessarily take a pretty much single threaded view. The compiler/jit will then notice that you don't touch reference in your code at all, therefore it can move the comparison outside the loop. It is free to do so, since you basically create a race condition (no synchronization/atomic accesses).
Fixing it could either involve using synchronization mechanisms or add the volatile specifier to reference, thus telling the compiler/jit, that the variable can be changed from outside the method.
Is there any reason why you would create locks around the getter and setter of a boolean property like this?
private _lockObject = new object();
private bool _myFlag;
public bool MyFlag
{
get
{
lock (_lockObject)
{
return _myFlag;
}
}
set
{
lock (_lockObject)
{
_myFlag = value;
}
}
}
Well, you don't need locks necessarily - but if you want one thread to definitely read the value that another thread has written, you either need locks or a volatile variable.
I've personally given up trying to understand the precise meaning of volatile. I try to avoid writing my own lock-free code, instead relying on experts who really understand the memory model.
EDIT: As an example of the kind of problem this can cause, consider this code:
using System;
using System.Threading;
public class Test
{
private static bool stop = false;
private bool Stop
{
get { return stop; }
set { stop = value; }
}
private static void Main()
{
Thread t = new Thread(DoWork);
t.Start();
Thread.Sleep(1000); // Let it get started
Console.WriteLine("Setting stop flag");
Stop = true;
Console.WriteLine("Set");
t.Join();
}
private static void DoWork()
{
Console.WriteLine("Tight looping...");
while (!Stop)
{
}
Console.WriteLine("Done.");
}
}
That program may or may not terminate. I've seen both happen. There's no guarantee that the "reading" thread will actually read from main memory - it can put the initial value of stop into a register and just keep using that forever. I've seen that happen, in reality. It doesn't happen on my current machines, but it may do on my next.
Putting locks within the property getter/setter as per the code in the question would make this code correct and its behaviour predictable.
For more on this, see this blog post by Eric Lippert.
Reads and writes of bool are atomic.
However the name "flag" indicates that separate threads will be reading/writing until some condition occurred. To avoid unexpected behavior due to optimization you should consider adding the volatile keyword to you bool declaration.
There's no reason to have a lock right there.
Taking a lock may well be appropriate in your design, but it's very doubtful that this is the right granularity.
You need to make your design thread-safe, not individual properties (or even entire objects).