views:

212

answers:

3

I have a dictionary declared as follows

IDictionary<string, object> _objectIds = new Dictionary<string, object>();

I was experiencing some problems with it and it discovered that the instance returned false as a result of ContainsKey method and from the watch window I was sure that the item was there. So I created helper method

private bool IdsContainsKey(string key)
{
  lock (syncObject)
  {
     lock (_objectIds)
     {
       if (_objectIds.ContainsKey(key))
         return true; // A
       if (_objectIds.ContainsKey(key))
         return true; // B
       return _objectIds.ContainsKey(key); // C
     }
  }
}

During my debugging session I run into situation when the method exited in place B and sometimes I made to C returning true. Can anybody help me? Thanks.

+5  A: 

You need to make sure you put a lock around every place you use _objectIds in order to be sure you are synchronizing properly.

Oded
well, lock on syncObject is placed everywhere, in fact I pass a wrapper dictionary, that is recording each access or method call to inner dictionary and there are records for only one thread only
Karel Frajtak
Why is a lock on `_objectIds` required if access to that object is already protected by a lock on `syncObject`? I don't see the value in having a double-lock pattern here.
Scott Dorman
I admit that this lock is redundant but I didn't know what to do, so I tried everything including this...
Karel Frajtak
A: 

Is there a reason for locking twice? I think


private bool IdsContainsKey(string key)
{
  lock (syncObject)
  {
    ...
  }
}

should do it. Althought I read somewhere that it's never a good idea to lock the instance with itself.

DHN
But I am not locking the instance itself.
Karel Frajtak
Sure you do. "lock (_objectIds)" is locking the calls on an instance with itself.
DHN
A: 

You don't need the lock(_objectIds) block. Also, why are you using a wrapper dictionary? Since you are using a generic Dictionary<TKey, TValue>, you should derive your own custom dictionary and implement your tracking there. Finally, your code would be better written as:

private bool IdsContainsKey(string key) 
{ 
   lock (syncObject) 
   {
      return _objectIds.ContainsKey(key); 
   } 
}

The result of the method is going to be entirely dependent upon the value you pass in as key. I suspect the problems you are encountering are due to incorrect locking in other places, an issue with your wrapper dictionary, or you aren't passing in the key you think you are.

Scott Dorman
Wrapper dictionary is used for diagnostic purpose only. I can assure you that every method of the class that contains _objectIds dictionary is "secured" with lock section and _objectIds is declared as private.
Karel Frajtak