A TimedLock
By Liang Zhang - Last updated: Tuesday, March 9, 2010 - Save & Share - Leave a Comment
The original article is from here
Because the nice-looking .Net lock keyword is translated with try{Monitor.Enter(obj);}finally{Monitor.Exit(obj)}, there is no timeout for Monitor.Enter, that may make it easier to cause some deadlock issues. That’s why Ian Griffiths invented his new lock. He and some other guys discussed a lot about how to improve the lock both in efficiency and usability. I am not going to talk much.
the code is like below:
using System; using System.Threading; // Thanks to Eric Gunnerson for recommending this be a struct rather // than a class - avoids a heap allocation. // Thanks to Change Gillespie and Jocelyn Coulmance for pointing out // the bugs that then crept in when I changed it to use struct... // Thanks to John Sands for providing the necessary incentive to make // me invent a way of using a struct in both release and debug builds // without losing the debug leak tracking. public struct TimedLock : IDisposable { public static TimedLock Lock (object o) { return Lock (o, TimeSpan.FromSeconds (10)); } public static TimedLock Lock (object o, TimeSpan timeout) { TimedLock tl = new TimedLock (o); if (!Monitor.TryEnter (o, timeout)) { #if DEBUG System.GC.SuppressFinalize(tl.leakDetector); #endif throw new LockTimeoutException (); } return tl; } private TimedLock (object o) { target = o; #if DEBUG leakDetector = new Sentinel(); #endif } private object target; public void Dispose () { Monitor.Exit (target); // It's a bad error if someone forgets to call Dispose, // so in Debug builds, we put a finalizer in to detect // the error. If Dispose is called, we suppress the // finalizer. #if DEBUG GC.SuppressFinalize(leakDetector); #endif } #if DEBUG // (In Debug mode, we make it a class so that we can add a finalizer // in order to detect when the object is not freed.) private class Sentinel { ~Sentinel() { // If this finalizer runs, someone somewhere failed to // call Dispose, which means we've failed to leave // a monitor! System.Diagnostics.Debug.Fail("Undisposed lock"); } } private Sentinel leakDetector; #endif } public class LockTimeoutException : ApplicationException { public LockTimeoutException () : base("Timeout waiting for lock") { } }
Posted in Dot Net • • Top Of Page