I am currently working on a project in C#. I am syncing access to a state variable using a single lock. This state variable is triggered to be set for a given period of time and then should have its value reset. My current code is as follows.
using System.Threading;
class Test
{
object syncObj = new object();
bool state = false;
Timer stateTimer;
Test()
{
stateTimer = new Timer(ResetState, this, Timeout.Infinite, Timeout.Infinite);
}
void SetState()
{
lock(syncObj)
{
state = true;
stateTimer.Change(1000, Timeout.Infinite);
}
}
static void ResetState(object o)
{
Test t = o as Test;
lock(t.syncObj)
{
t.state = false;
}
}
}
Given that it is valid to call SetState again before ResetState is called by the Timer (i.e. it is allowed to extend the period of time that state is true), I can imagine situations where a single lock may not be enough. The specific case I'm thinking of is this
- Both SetState and ResetState are entered at the same time, on the main thread and the Timer thread respectively
- SetState acquires the lock first and correctly sets state to true and triggers the timer to start again
- ResetState then incorrectly sets state to false meaning that state is not true for the expected period of time
I've been scratching my head over this one for a little while. The closest I got to being able to solve it was by using two locks but in the end I found this caused other issues (at least, the way I'd done it).
Is there a known way to solve this problem (and should I be reading something to refresh my knowledge of synchronisation)?
UPDATE: I forgot to mention that the current state of the timer cannot be queried in this instance. If it could I would imagine checking the remaining time in ResetState to determine that the timer is really stopped.