Csharp/CSharp Tutorial/Thread/Thread DeadLock
A sure-fire deadlock
<source lang="csharp">using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime; using System.Runtime.rupilerServices; using System.Security; using System.Text; using System.Threading; public class MainClass {
private static object deadlockA = new object(); private static object deadlockB = new object(); public static void Main() { lock (deadlockA) { ThreadPool.QueueUserWorkItem(delegate { lock (deadlockB) { Console.WriteLine("A"); lock (deadlockA) { Console.WriteLine("B"); } } }); lock (deadlockB) { Console.WriteLine("Main: got b"); } } }
}</source>
Main: got b A B
Dining Philosopher
<source lang="csharp">/* Quote from C# and the .NET Framework by Bob Powell
- /
using System; using System.Threading; public struct PhilosopherData {
public int PhilosopherId; public Mutex RightChopStick; public Mutex LeftChopStick; public int AmountToEat; public int TotalFood;
}
public class Philosopher : WorkerThread {
public Philosopher( object data ) : base( data ) { } protected override void Run( ) { PhilosopherData pd = (PhilosopherData)Data; Random r = new Random( pd.PhilosopherId ); Console.WriteLine("Philosopher {0} ready", pd.PhilosopherId ); WaitHandle[] chopSticks = new WaitHandle[] { pd.LeftChopStick, pd.RightChopStick }; while( pd.TotalFood > 0 ) { //Get both chop sticks WaitHandle.WaitAll( chopSticks ); Console.WriteLine("Philosopher {0} eating {1} of {2} food", pd.PhilosopherId, pd.AmountToEat, pd.TotalFood ); pd.TotalFood -= pd.AmountToEat; Thread.Sleep( r.Next(1000,5000) ); //Release the chopsticks Console.WriteLine("Philosopher {0} thinking", pd.PhilosopherId); pd.RightChopStick.ReleaseMutex( ); pd.LeftChopStick.ReleaseMutex( ); //Think for a random time length Thread.Sleep( r.Next(1000,5000) ); } Console.WriteLine("Philosopher {0} finished", pd.PhilosopherId ); }
}
public class Restaurant {
public static void Main( ) { Mutex[] chopSticks = new Mutex[5]; //init the chopSticks for( int i = 0; i < 5; i++ ) chopSticks[i] = new Mutex( false ); //Create the Five Philosophers for( int i = 0; i < 5; i++ ) { PhilosopherData pd; pd.PhilosopherId = i + 1; pd.RightChopStick = chopSticks[ i - 1 >= 0 ? ( i - 1 ) : 4 ]; pd.LeftChopStick = chopSticks[i]; pd.AmountToEat = 5; pd.TotalFood = 35; Philosopher p = new Philosopher( pd ); p.Start( ); } Console.ReadLine( ); }
} public abstract class WorkerThread {
private object ThreadData; private Thread thisThread;
//Properties public object Data { get { return ThreadData; } set { ThreadData = value; } } public object IsAlive { get { return thisThread == null ? false : thisThread.IsAlive; } } /// <summary> /// Constructors /// </summary> public WorkerThread( object data ) { this.ThreadData = data; } public WorkerThread( ) { ThreadData = null; } /// <summary> /// Public Methods /// </summary> /// <summary> /// Start the worker thread /// </summary> public void Start( ) { thisThread = new Thread( new ThreadStart( this.Run ) ); thisThread.Start(); } /// <summary> /// Stop the current thread. Abort causes /// a ThreadAbortException to be raised within /// the thread /// </summary> public void Stop( ) { thisThread.Abort( ); while( thisThread.IsAlive ) ; thisThread = null; } /// <summary> /// To be implemented by derived threads /// </summary> protected abstract void Run( );
}</source>
Philosopher 1 ready Philosopher 1 eating 5 of 35 food Philosopher 2 ready Philosopher 3 ready Philosopher 3 eating 5 of 35 food Philosopher 4 ready Philosopher 5 ready Philosopher 1 thinking Philosopher 5 eating 5 of 35 food Philosopher 3 thinking Philosopher 2 eating 5 of 35 food Philosopher 5 thinking Philosopher 4 eating 5 of 35 food ^CTerminate batch job (Y/N)? n