I have long? startTime
to hold start time.
I have multiple threads with non-async
methods updating startTime
and there's another async
method in a separate thread that only ever read this value. The methods that update the value do so as below:
if (startTime == null || (newValue != 0 && newValue < startTime))
{
startTime = newValue;
}
The issue is that, writer threads are updating startTime
at a very very high frequency causing a lot of contention for the lock. So, is there any way I can do this without locking (or a better locking mechanism over a normal lock)?
I'm thinking of using Interlocked
but because of the if
clause, I think this is not correct?
EDIT: I can change it to a non-nullable if needed.
From end of question:
EDIT: I can change it to a non-nullable if needed.
For the non-nullable long
, you need a check and update loop (something like this):
var current = Interlocked.Read(ref startTime);
while(current > newValue)
{
var other = Interlocked.CompareExchange(ref startTime, newValue, current);
if(other==current) break;
current = other;
}
You can make your while clause conditions arbitrarily complex, they're effectively your if
check. You may also want/need to recompute newValue
inside the loop as well.
The Interlocked.Read
obtains you the initial value. The Interlocked.CompareExchange
does "if the value is still the same as when I last read the value, commit my change" and also obtains the new current value if the value had changed.
Other things to consider - do you actually need this "start time" value or could a simple incrementing integer stand in it's place? That would be Interlocked.Increment
with no looping and no locking, so may be worth considering if write contention is still high here, if you can modify the other parts of your code appropriately.