views:

302

answers:

7

I have the following code:

            locker = new object();
        lock (locker)
        {
            for (int i = 0; i < 3; i++)
                 ver_store[i] = atomic_Poll(power);                
        }

I was just wandering, considering the function within the lock accesses some global resources, (an open socket among them) whether all global resources within the obeject is also locked. ( I am aware that any other function that accesses these same variables must implement a lock them also for the locking mechanism to be valid. I just haven't gotten round to locking them yet :) )

+4  A: 

It's very simple- the lock locks code within the lock statement. If you are using those resources elsewhere in your code, they won't be covered by that lock.

Some classes have mechanisms on them so you can lock in multiple places- an example of this is the Hashtable's Syncroot property. The usefulness of this is questionable though. A nice discussion about it is on SO.

Your best bet is encapsulating this logic in its own class, with an internal locking mechanism, and make sure your app uses just that class.

RichardOD
+1  A: 

Lock doesn't relate to some object - it relates only to piece of code. So if you have 2 different function that works with global socket, you must control both of them, for your example it must be same 'locker' object - so make it visible for both piece of code.

Dewfy
+4  A: 

The lock only affects the code in the lock-statement body. The objects passed as a parameter acts as a unique identifier, it is not affected internally in any way.

sharptooth
+1  A: 

Short answer: No

Locking is a logical concept, not a physical one where the language/cpu infers the scope of a lock and restricts access to all items within the scope. It's your job to enforce lock usage, so if you have to acquire lock X to use resource Y then you must ensure you always do this.

Sean
+3  A: 

As mentioned by everybody over here...

  • lock is a logical concept
  • lock only locks what is there in the block of code within curly braces.

But to give you a brief insight:

lock is nothing but a replacement for Monitor.Enter and Monitor.Exit. Just that, with lock Monitor.Exit is placed in a finally block.

So, what you are ACTUALLY locking is (in your code) is the locker object. So, anywhere in your code if you use this locker object for locking then that block of code will be locked.

My guess is this is how your lock works: (gurus, please correct me if I am wrong)

if(locker.SyncBlockIndex <0)>                                                       
{                                                                                
//obtain an index to free synch cache block                                      
//assign the index obtained in previous step to obj.SyncBlockIndex               
}                                                                                
syncblock = syncblockCache[locker.SyncBlockIndex]                                   
if(!syncblock is owned by the calling thread)                                    
{                                                                                
//susped the calling thread                                                      
}

See if this link helps you understand the lock (I had written this post sometime ago)

http://dotenetscribbles.blogspot.com/2008/10/calling-monitorenter-recursively.html

P.K
+2  A: 

A lock is just a token. As long as some thread is holding a specific lock other threads will not be allowed to obtain that lock and thus be prevented from running code that is synchronized using the lock in question.

You may want to check the answers to this question as well: http://stackoverflow.com/questions/753168/does-lock-lock-a-resource-or-does-it-lock-a-piece-of-code/753270#753270

Brian Rasmussen
+8  A: 

The lock statement does NOT "lock code" or any resource that goes in between the curly braces pre se.

I find it best to understand lock from a thread perspective (after all, threading scenarios is when you need to consider locking).

Given your sample code

10  locker = new object();
11  lock (locker)
12  {
     ...
15  }

When thread X reaches line 10 a new object is created and at line 11 a lock is acquired on the object. Thread X continues to execute whatever code is within the block.

Now, while thread X is in the middle of our block, thread Y reaches line 10. Lo and behold, a new object is created, and since it is created by thread Y no lock is currently acquired on this object. So when thread Y reaches 11 it will successfully acquire a lock on the object and continues to execute the block concurrently with thread X.

This is the situation the lock was suppose to prevent. So what to do? Make locker a shared object.

01  static object locker = new object();

    ...

11  lock (locker)
12  {
     ...
15  }

Now, when thread X reaches line 11 it will acquire the lock and start executing the block. When thread Y reaches line 11 it will try to acquire a lock on the same object as thread X. Since this object is already locked, thread Y will wait until the lock is released. Thus preventing concurrent execution of the code block, thus protecting any resources used by that code to be accessed concurrently.

Note: if other parts of your system should be serialized around the same resources they must all try to lock the same shared locker object.

Peter Lillevold
An even better explanation for a beginner. Thank you oh so much
Dark Star1
You are so totally welcome :)
Peter Lillevold