I have a private collection (like an ISet<int>
) that can be accessed or modified by several threads.
I have logic such that this thread only needs to mutate the ISet
in certain states, whereas the other thread always needs to mutate it. The other thread will always take a lock
, implemented the lock
keyword on the ISet
like this:
lock (this._set)
{
// some mutating operation on this._set
}
For this thread, I only need to perform an operation that mutates the thread if the ISet
contains an int
called currentValue
, which in this case is rare. The operation in the other thread is frequent. Therefore the question is whether I can check to see if the ISet
contains currentValue
before taking the lock
, to minimize the time that this thread blocks the other thread, like this:
if (this._set.Contains(currentValue))
{
lock (this._set)
{
if (this._set.Contains(currentValue))
{
// some mutating operation on this._set
}
}
}
The question is whether the behavior of the check outside the lock
is undefined, or if it can result in the ISet
being put into an undefined or unexpected state. Of course the actual value returned cannot be trusted to use, which is why it's checked again inside the lock
, but is this a valid optimization that I can expect to work, or will it mess up some internal state of the set? The goal is to take the lock
in this thread as rarely as possible.