3

Two questions about the Lock() construct in .net

First, I am aware that if an object is locked within one class and another class attempts to lock the same object this produces a deadlock. But why? I have read about it on MSDN but MSDN is rarely all that clear.

----Edit Question One---- Still confused. I have a main thread (UI thread) that spawns many Threadpool threads. Each child thread locks the data before it works with it. This works fine every time.

If I then attempt to lock the same data from the UI thread to check if I should even bother creating a new thread for an edge case I create deadlock nearly every time.

----Edit Question Two---- Secondly, If I have a compound object that I lock are all child objects within it locked as well? Short code Demo:

internal sealed class Update
{
    //Three objects instantiated via other external assemblies
    public DataObject One { get; set; }
    public DataObject Two { get; set; }
    public ReplayStatus Status { get; set; }
}

If I call lock(UpdateObject) are each of the three internal objects and all of there child objects locked as well?

So I should do somthing like this to prevent threads from playing with my data objects:

Lock(UpdateObject.One)
{
    Lock(UpdateObject.Two)
    {
        Lock(UpdateObject.Status)
        {
            //Do Stuff
        }
    }
} 
Ritz
  • 203
  • 1
  • 2
  • 10
  • [Great article on deadlocks](http://msdn.microsoft.com/en-us/magazine/cc163618.aspx), assuming this isn't the one that was unclear. – Brad Christie Apr 26 '12 at 01:52
  • So a follow up would be that Lock can prevent all of my threadpool threads form creating race conditions. Good solution for part of my code but not enough to solve the new problems that my coed is facing. I need to use a mutex to prevent access to to data from different code segments. – Ritz Apr 26 '12 at 02:45

2 Answers2

5

First, I am aware that if an object is locked within one class and another class attempts to lock the same object this produces a deadlock.

No. If one thread locks an object and a second thread attempts to lock that object, that second thread must wait for the first thread to exit the lock.

Deadlock is something else:

1. thread1 locks instanceA
2. thread2 locks instanceB
3. thread1 attempts to lock instanceB and now must wait on thread2
4. thread2 attempts to lock instanceA and now must wait on thread1

These two threads can no longer execute, and so never release their locks. What a mess.

If I call lock(UpdateObject) are each of the three internal objects and all of there child objects locked as well?

No, the "lock" is only on the locked instance. Note: the lock doesn't prevent anything other than a second thread from acquiring a lock on that instance at the same time.

Amy B
  • 108,202
  • 21
  • 135
  • 185
3

First, the whole point of a lock is that two sections of code can't get ahold of the same lock at once. This is to coordinate multiple threads working with the same stuff without interfering with each other. If you have a lock on an object, then anyone else that tries to get the lock will block (wait) until the original lock is released (only one thread can have the lock at any given time). You only have a deadlock if the first thread never gives up the lock, or if both threads are waiting for something from each other and neither can proceed until each gets what it's waiting for.

Second, if you lock an object in C#, you're not really "locking" the object in any semantic sense. You're acquiring a "lock" on the object (which you later release or relenquish). The object is purely a convenient token that is used to uniquely identify which lock you wish to obtain. So no, a lock on an object does not create a lock on any sub-parts of that object.

Cameron
  • 96,106
  • 25
  • 196
  • 225
  • Updated my question to reflect your response – Ritz Apr 26 '12 at 02:28
  • 1
    @Ritz: Locking an object doesn't prevent another thread from using it. It only prevents another lock from being acquired on the same object. – Cameron Apr 26 '12 at 02:29
  • Cameron, I just got it. I need a Mutex! – Ritz Apr 26 '12 at 02:36
  • 1
    @Ritz: A lock is still the simplest way to do that. You just make sure that all the code that works on the data is wrapped in a lock on some object (the same object for each section of code that can modify the data). This way, while one section is doing stuff, if another section wants to also do stuff, it has to wait, but as soon as the first section finishes, the lock is released and the second section then gets the lock and can do its thing safely. – Cameron Apr 26 '12 at 02:41
  • 1
    @Ritz: In response to your edited comment: A lock (which uses a monitor internally) provides almost the same functionality as a mutex, but is faster. It's probably all you need. See http://stackoverflow.com/questions/1164038/monitor-vs-mutex-in-c-sharp – Cameron Apr 26 '12 at 02:44