RSS 2.0

Personal Info:

Joe Send mail to the author(s) works on parallel libraries, infrastructure, and programming models in Microsoft's Developer Division.

Blogroll:
Other
News
 C|Net
 Kuro5hin
 The Register
Technology
 <?xmlhack?>
 Daily WTF
 DevX
 Hacknot
 Java Today
 Microsoft Top 10 Downloads
 MSDN
 MSDN: "Longhorn"
 MSDN: XML Developer Center
 Slashdot
 Techdirt
 theserverside.com
 W3C
 Web Pages That Suck
 XML Cover Pages
 XML Journal
 xml.com
Technology Blogs
 Aaron Skonnard [PluralSight]
 Adam Bosworth [Google]
 Andy Rich [MS/C++]
 Arpan Desai [MS/XML]
 BCL Team [MS]
 Bill Clementson [Lisp]
 Bill de hÓra
 Bruce Eckel [J]
 Bruce Tate [J]
 Casey Chestnut
 Cedric Beust [Google]
 Chris Anderson [MS/Avalon]
 Chris Lyon [MS]
 Christian Weyer
 Clemens Vasters [newtelligence]
 Craig Andera [PluralSight]
 Dan Sugalski [Parrot]
 Daniel Cazzulino
 Dave Chappel
 Dave Roberts [Lisp]
 Dave Thomas [PragProg]
 Dave Winer
 Dion Almaer [J]
 Don Demsak
 Doug Purdy [MS/Indigo]
 Drew Marsh
 Eric Gunnerson [MS]
 Eric Rudder [MS]
 Eric Sink
 Fritz Onion [PluaralSight]
 Gavin King [J/Hibernate]
 Grady Booch [IBM]
 Hervey Wilson [MS/Indigo]
 Hillel Cooperman [MS/Shell]
 Howard Lewis Ship [J/Apache]
 Ingo Rammer [PluralSight]
 James Gosling [J/Sun]
 James Strachan [J/Groovy]
 Jason Matusow [MS/OSS]
 Jeffrey Schlimmer [MS/Indigo]
 Joe Beda [Google]
 Joel Spoelsky
 Jon Udell
 Josh Ledgard [MS/Evang]
 Joshua Allen [MS]
 Lambda
 Larry Osterman [MS]
 Maoni Stephens [MS/CLR]
 Mark Fussell [MS/XML]
 Martin Fowler
 Martin Gudgin [MS/Indigo]
 Me
 Michael Howard [MS]
 Miguel de Icaza [Mono]
 Mike Clark
 Omri Gazitt [MS/Indigo]
 Pat Helland [MS/PAG]
 Pinku Surana
 Raymond Chen [MS]
 Rich Lander [MS/CLR]
 Rob Howard
 Rob Relyea [MS/Avalon]
 Robert Cringely
 S. Somasegar [MS/DevDiv]
 Sam Gentile
 Scoble [MS/Evang]
 Scott Guthrie [MS/WebNet]
 Scott Hanselman
 Sean McGrath [J]
 Simon Fell
 Stanley Lippman [MS/C++]
 Steve Maine
 Steve Swartz [MS/Indigo]
 Steve Vinoski
 Steven Clarke [MS/Usability]
 Stuart Halloway
 Ted Leung
 Ted Neward [DM]
 Tim Bray [Sun]
 Tim Ewald [Mindreef]
 Tim O'Reilly
 Werner Vogels [Amazon]
 Wintellect
 Yasser Shohoud [MS/Indigo]
Top 20
 Brad Abrams [MS/CLR]
 Chris Brumme [MS/CLR]
 Chris Sells [MS/Ultra]
 Cyrus Najmabadi [MS/C#]
 Dominic Cooney [MS/XAF]
 Don Box [MS/Ultra]
 Don Syme [MS/R]
 Guido van Rossum [Python]
 Herb Sutter [MS/C++]
 Ian Griffiths
 Jason Zander [MS/CLR]
 Jim Hugunin [MS/CLR]
 Joel Pobar [MS/CLR]
 Krzysztof Cwalina [MS/CLR]
 Patrick Logan
 Paul Graham
 Rico Mariani [MS/CLR]
 Rory Blyth [MS/DN]
 Sam Ruby
 Wesner Moise
VC/Business Blogs
 Ed Sim
 Fred Wilson
 Jonathan Schwartz [J/Sun]
 Lawrence Lessig [Stanford]
 Mark Cuban
 Michael Hyatt
 Pierre Omidyar
 Ross Mayfield
 VentureBlog
 Weekly Read
Wine, Food & Tea
 The Silk Road of Wine
 Vinography: a wine blog
 Wine Whys

Disclaimer:
The content of this site are my own personal opinions and do not represent my employer's view in anyway.

© 2008, Joe Duffy

 
 Sunday, June 24, 2007

In response to a previous post, a reader said

“I was under the impression that monitors were implemented in .NET in a multiplexed way, so that events are only allocated to an object while there is contention - and that they aren't "sticky", becoming permanently attached to the object.”

This is absolutely correct.  My nulling out of the object reference in the example only has the slight advantage of promoting the object’s collection sooner, but it does not have the effect of speeding up the reclamation of the internally managed monitor state.  My original posting erroneously said that it would.

Let’s take a quick step back, and see exactly what this means.

Monitors are comprised of two capabilities: critical regions (i.e. Monitor.Enter and Exit), to achieve mutual exclusion, and condition variables (i.e. Monitor.Wait, Pulse, and PulseAll), to coordinate between threads.  Any CLR object can be used as a monitor.

For the critical region case, the CLR uses an efficient thin lock which simply embeds locking information as a bit pattern inside the object’s header word.  Other parts of the system also try to use the header, e.g. when caching an object’s default hash-code, COM interop, etc.  There are limits to what can be stored in the header, so use of any two of these things simultaneously causes inflation, meaning the object header’s contents become an index into a table of sync blocks.  Sync blocks are just little data structures capable of holding all of that state simultaneously.  The CLR manages a system-wide table of them and recycles and reuses them as objects need them.  Another event that causes inflation is the first occasion on which a thread tries to enter the critical region while another thread holds it (i.e. contention).

When contention arises, the CLR will spin briefly before truly waiting, but it may eventually need to allocate a Windows kernel event object.  This is an auto-reset (synchronization) event, and a handle to it gets stored on the sync block.   Waiting threads just wait on it, and threads exiting the critical region will set it (if the wait count is non-zero).  Note that this leads to unfair behavior, because threads can steal the critical region between the signal and the wake-up, but helps to prevent convoys.

Condition variables are implemented slightly differently.  Each CLR thread object has a single event object dedicated to it.  The first time a thread calls Wait on a condition variable, the event is lazily allocated.  And then the thread simply places its own thread-local event into a list of events associated with the monitor.  Registering the event also requires inflation to a sync block, if it hasn’t happened already, because obviously the event list can’t be stored in the object header.  When a Pulse happens, the pulsing thread just signals the first event in the list.  Waiting and pulsing is thus actually somewhat fair, but there are other races that can eliminate this that I won't get into.  When a PulseAll occurs, the pulsing thread walks the whole list and signals each.

So now back to the question: when are sync blocks reclaimed?

When a GC is triggered, objects in the reachability traversal may have their sync blocks reclaimed, even if the object in question is still alive, and made available again in the system-wide pool of reusable sync blocks.  This reclamation can happen so long as the sync block isn’t needed permanently (as would be the case if COM interop information was stored inside of it) and the sync block isn’t marked precious.  A sync block is precious anytime there is a thread inside of the object’s critical region, when a thread is waiting to enter the critical region, or when at least one thread has registered its event into the associated condition variable list.  Notice that orphaning monitors can thus lead to leaking events, because they will remain precious, unless the monitor object itself becomes unreachable.  When a sync block is reclaimed in this fashion, certain reusable state is kept, like the critical region event object, so that the next monitor to use the sync block can reuse it.

6/24/2007 12:14:35 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [2]

 

Recent Entries:

Search:

Browse by Date:
<July 2008>
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

Browse by Category:

Notables:

Currently Up To:

Reading...

Listening...

Watching...