none
Does SyncLock (or lock in c#) just wrap a Win32 CRITICAL_SECTION ? RRS feed

  • Question

  • OK so I've recently been trying to find out exactly how SyncLock works behind the scenes, just out of curiosity really, and so far I have the following understanding:

    SyncLock is essentially just a nice tidy way to use the Monitor.Enter and Monitor.Exit methods, it wraps the calls in a Try/Finally block and places the Monitor.Exit call in the Finally block so that it is always called. A Monitor is a pure .NET thing (as opposed to Mutexes and Semaphore's which just wrap the Win32 equivelants) that makes use of the SyncBlockIndex header field that any .NET object has. When an object is used for locking by SyncLock/Monitor it just points the SyncBlockIndex field of that object to a SyncBlock in the CLR's cache of SyncBlocks and this SyncBlock keeps track of which thread currently owns it. If another thread comes along and tries to lock on the same object then it will see that another thread currently owns the SyncBlock associated with that object so it will be suspended and will await notification of the SyncBlock becoming available. Then when you reach the End SyncLock or Monitor.Exit the SyncBlockIndex field is set back to nothing to indicate that no thread is currently owning a SyncBlock for this object.

    Is that all correct? I thought I had a fairly decent understanding of it but then I read this article (http://blogs.techrepublic.com.com/programming-and-development/?p=86) which says that SyncLock uses the Win32 CRITICAL_SECTION structure (where as my understanding is that SyncLock and the SyncBlockIndex header field implement a similar system to the Win32 CRITICAL_SECTION but SyncLock does not just call down to a CRITICAL_SECTION behind the scenes)

    Thanks
    Chris

    EDIT: After reading this (http://msdn.microsoft.com/en-us/magazine/cc163552.aspx#S7) I am inclined to believe that SyncLock/Monitor do not make any use of the native Win32 CRITICAL_SECTION structure but I would still be greatful if someone could just confirm that my general understanding of how SyncLock works is correct :)

    Also, does anyone know how a thread actually knows when an object is no longer locked? I mean I assume it is not constantly checking the owner of the SyncBlock or whatever because there seems to be no intensive CPU activity when a thread is waiting on a locked object. So does the thread just register itself as waiting for that object, then go to sleep and the CLR will start the thread up again when the SyncBlock is free?



    My blog: http://cjwdev.wordpress.com
    Friday, December 25, 2009 2:05 AM

Answers

All replies

  • You are asking an internal technical detail about the implementation of CLR. Such internal details are seldom documented and can change at any time (because they do not matter to .NET users).

    Your basic understanding is IMO correct. Also I don't think CLR uses Win32 critical section for SyncBlocks - you can btw confirm it on your own by setting breakpoints to Windows APIs and watch if/when your .NET app will stop on those.

    If you really want to dig deeper, I would recommend you to check out Rotor sources (there's also a book about Rotor).

    -Karel
    Friday, December 25, 2009 11:35 PM
    Moderator
  • The lock/SyncLock statements do not use CRITICAL_SECTION. In particular, on STA threads, they will pump some windows messages.

           -Steve
    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ

    Microsoft Certified Professional Developer
    • Marked as answer by Chris128 Saturday, December 26, 2009 11:32 PM
    Saturday, December 26, 2009 12:10 AM
  • You are asking an internal technical detail about the implementation of CLR. Such internal details are seldom documented and can change at any time (because they do not matter to .NET users).

    Your basic understanding is IMO correct. Also I don't think CLR uses Win32 critical section for SyncBlocks - you can btw confirm it on your own by setting breakpoints to Windows APIs and watch if/when your .NET app will stop on those.

    If you really want to dig deeper, I would recommend you to check out Rotor sources (there's also a book about Rotor).

    -Karel

    Thanks for the answer, I dont know how I would set a breakpoint on a Win32 critical section though... or even which program I would need to use to do such a thing. After all the Win32 critical section is a structure isnt it? A type definition. How would you set a breakpoint on a type definition?

    I have already downloaded the shared source CLI libraries and tried to track down how Monitor.Enter (which is defined as the method JIT_MonEnter in the call mapping file (eccmp.cpp or something like that) but as I dont know the first thing about C++ I am not really getting anywhere. If I cant find out how it works internally then its not the end of the world, I was just curious :) and like I said, I just wanted to know if it used a win32 critical section but you guys have confirmed my thoughts (that it does not).

    Thanks
    Chris
    My blog: http://cjwdev.wordpress.com
    Saturday, December 26, 2009 11:27 PM
  • The Rotor implementation of Monitor is interesting, and rather complex. I took a look at it a while ago, to see if it suffered from an obscure bug: http://nitoprograms.blogspot.com/2009/09/if-pusleevent-is-broken-what-about.html.

    It probably does use a critical section (or more properly, several of them) at various points, but it is not just a simple wrapper. Far from it. :)

           -Steve
    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ

    Microsoft Certified Professional Developer
    Sunday, December 27, 2009 3:29 AM