Race Cars

Page 80

rw.EnterWriteLock(); rw.EnterReadLock(); Console.WriteLine (rw.IsReadLockHeld); Console.WriteLine (rw.IsWriteLockHeld); rw.ExitReadLock(); rw.ExitWriteLock();

// True // True

The basic rule is that once you’ve acquired a lock, subsequent recursive locks can be less, but not greater, on the following scale: Read Lock Upgradeable Lock Write Lock A request to promote an upgradeable lock to a write lock, however, is always legal.

Suspend and Resume A thread can be explicitly suspended and resumed via the deprecated methods Thread.Suspend and Thread.Resume. This mechanism is completely separate to that of blocking. Both systems are independent and operate in parallel. A thread can suspend itself or another thread. Calling Suspend results in the thread briefly entering the SuspendRequested state, then upon reaching a point safe for garbage collection, it enters the Suspended state. From there, it can be resumed only via another thread that calls its Resume method. Resume will work only on a suspended thread, not a blocked thread. From .NET 2.0, Suspend and Resume have been deprecated, their use discouraged because of the danger inherent in arbitrarily suspending another thread. If a thread holding a lock on a critical resource is suspended, the whole application (or computer) can deadlock. This is far more dangerous than calling Abort—which results in any such locks being released (at least theoretically) by virtue of code in finally blocks. It is, however, safe to call Suspend on the current thread—and in doing so you can implement a simple synchronization mechanism—ith a worker thread in a loop, performing a task, calling Suspend on itself, then waiting to be resumed (“woken up”) by the main thread when another task is ready. The difficulty, though, is in determining whether the worker is suspended. Consider the following code: worker.NextTask = "MowTheLawn"; if ((worker.ThreadState & ThreadState.Suspended) > 0) worker.Resume; else // We cannot call Resume as the thread's already running. // Signal the worker with a flag instead: worker.AnotherTaskAwaits = true;

This is horribly thread-unsafe: the code could be preempted at any point in these five lines, during which the worker could march on in and change its state. While it can be worked around, the solution is more complex than the alternative—using a synchronization construct such as an AutoResetEvent or Wait and Pulse. This makes Suspend and Resume useless on all counts. The deprecated Suspend and Resume methods have two modes: dangerous and useless!

Aborting Threads You can end a thread forcibly via the Abort method:

© 2006-2010 Joseph Albahari, O’Reilly Media, Inc. All rights reserved. www.albahari.com/threading/

80


Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.