1

Is it possible to get a value which indicates how many threads are waiting to acquire a lock on a certain object?

toplel32
  • 1,162
  • 1
  • 7
  • 22

1 Answers1

1

No, but you could incapsulate the lock in a class that does:

Interlocked.Increment

before entering the lock on a counter and

Interlocked.Decrement

after attaining the lock

For example:

public sealed class SimpleCountedLock
{
    private readonly object obj = new object();

    private int counter;

    public int Counter
    {
        get
        {
            // Guaranteed to return the last value
            return Interlocked.CompareExchange(ref counter, 0, 0);
        }
    }

    public void Enter(ref bool lockTaken)
    {
        int cnt = int.MinValue;

        try
        {
            try
            {
            }
            finally
            {
                // Finally code can't be interrupted by asyncronous exceptions
                cnt = Interlocked.Increment(ref counter);
            }

            Monitor.Enter(obj, ref lockTaken);
        }
        finally
        {
            // There could be an asynchronous exception (Thread.Abort for example)
            // between the try and the Interlocked.Increment .
            // Here we check if the Increment was done
            if (cnt != int.MinValue)
            {
                Interlocked.Decrement(ref counter);
            }
        }
    }

    public void Exit()
    {
        Monitor.Exit(obj);
    }
}

Use:

SimpleCountedLock cl = new SimpleCountedLock();

and then in the various threads:

bool lockTaken = false;

try
{
    cl.Enter(ref lockTaken);
    // Your code. The lock is taken
}
finally
{
    if (lockTaken)
    {
        cl.Exit();
    }
}

The reasoning for the ref lockTaken is here: Monitor.Enter.

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • It appears not; http://stackoverflow.com/questions/4628243/is-the-operator-thread-safe – toplel32 Feb 28 '15 at 18:03
  • @toplel32 Yep, `++` and `--` aren't thread safe, nor is reading 64 bit values (`long`) when your app is 32 bits – xanatos Feb 28 '15 at 18:10
  • @toplel32 Fixed the typo :-) – xanatos Feb 28 '15 at 18:20
  • Is the `Finally` block crucial for the `Interlock.Increment` call? If so, is there an uniform way to solve the problem? – toplel32 Feb 28 '15 at 18:56
  • @toplel32 If you aren't interested in the counter being "exact" in case of asyncronous exceptions (consider that only `Thread.Abort ` doesn't kill the program, the other two async exceptions are "very bad errors" that will always kill the program), then you can remove all the try... except of the `Enter` method. – xanatos Feb 28 '15 at 19:01