Threading deep dive – Day 6
What are locks?
When there is a shared value that can be accessed by all the threads from your application, data become invalid is possible. Remember we discussed this issue in previous days. So we have to synchronize the access across all threads. How? There come the locks. There is "lock" statement available in C# using which one can lock on some reference type and proceed using the resource. If all other threads from your application also follow this approach [locking on one specific reference type and then continue using the resource], CLR guarantees that would allow only one thread at a time in the lock controlled statements. All other threads would be waiting on the lock statement itself till the thread that gone inside the lock block completes its execution and come out of the block. You may aware that lock internally uses Monitor based locks. There are different kinds of locking mechanisms available with CLR like Monitors, Mutexes, Semaphores etc. You can use these locks based on your requirements like Inter-appdomain, Inter-process , intra-appdomain and intra-process locking.
Below code sample describes the lock usage in C#
object lockOb = new object();
lock (lockOb)
{
// some operations
}
Below is the call stack of the thread that waits on the lock
ntdll!KiFastSystemCallRet
ntdll!NtWaitForMultipleObjects
KERNEL32!WaitForMultipleObjectsEx
mscorwks!WaitForMultipleObjectsEx_SO_TOLERANT
mscorwks!Thread::DoAppropriateAptStateWait
mscorwks!Thread::DoAppropriateWaitWorker
mscorwks!Thread::DoAppropriateWait
mscorwks!CLREvent::WaitEx
mscorwks!CLREvent::Wait
mscorwks!AwareLock::EnterEpilog
mscorwks!AwareLock::Enter
JIT_MonEnterWorker_Portable
I have taken this stack using winDBG. The call stack reveals that the thread could not acquire the lock, waits by calling the function NtWaitForMultipleObjects from ntdll.dll and then transitions to kernel mode by calling KiFastSystemCallRet function from the same dll. Here you may get the question in your mind like why the thread should transition into kernel mode for waiting? We will look later the relationship between thread waiting and kernel mode transitioning.
We use lock statements to synchronize access to resources. Is there any other ways available to synchronize data access? Yes.
We can make use of memory barriers which would force the processor to write all pending writes to RAM.
Lock free data structures where you need not to lock for read / write operations.
Interlocked operations that perform operations atomically.
Tomorrow let us see, what are atomic operations and their internals.
Comments
Anonymous
June 25, 2008
PingBack from http://wordnew.acne-reveiw.info/?p=3363Anonymous
November 23, 2008
Thanks for these great posts about threading. For a bit of additional info, the lock statement is an exclusive lock regardless of whether reads or writes are being done. ReaderWriterLock and ReaderWriterLockSlim provide a bit more flexibility in locking as they allow for multiple read locks to be held, but only one write lock.