1. The following sample uses threads and lock. As long as the lock statement is present, the statement block is a critical section and balance will never become a negative number.
// using System.Threading; class Account { private Object thisLock = new Object(); int balance; Random r = new Random(); public Account(int initial) { balance = initial; } int Withdraw(int amount) { // This condition never is true unless the lock statement // is commented out. if (balance < 0) { throw new Exception("Negative Balance"); } // Comment out the next line to see the effect of leaving out // the lock keyword. lock (thisLock) { if (balance >= amount) { Console.WriteLine("Balance before Withdrawal : " + balance); Console.WriteLine("Amount to Withdraw : -" + amount); balance = balance - amount; Console.WriteLine("Balance after Withdrawal : " + balance); return amount; } else { return 0; // transaction rejected } } } public void DoTransactions() { for (int i = 0; i < 100; i++) { Withdraw(r.Next(1, 100)); } } } class Test { static void Main() { Thread[] threads = new Thread[10]; Account acc = new Account(1000); for (int i = 0; i < 10; i++) { Thread t = new Thread(new ThreadStart(acc.DoTransactions)); threads[i] = t; } for (int i = 0; i < 10; i++) { threads[i].Start(); } } }
2. Here, Main constructs an App object and then enters this object's lock. At some point, a garbage collection occurs (in this code, the garbage collection is forced), and when App's Finalize method gets called, it attempts to lock the object. But, the CLR's Finalize thread can't acquire the lock because the application's primary thread owns the lock. This causes the common language runtime's Finalizer thread to stop—no more objects (in the process which can include multiple AppDomains) can get finalized and no more finalizable objects will ever have their memory reclaimed from within the managed heap!
using System; using System.Threading; class App { static void Main() { // Construct an instance of the App object App a = new App(); // This malicious code enters a lock on // the object but never exits the lock Monitor.Enter(a); // For demonstration purposes, let's release the // root to this object and force a garbage collection a = null; GC.Collect(); // For demonstration purposes, wait until all Finalize // methods have completed their execution - deadlock! GC.WaitForPendingFinalizers(); // We never get to the line of code below! Console.WriteLine("Leaving Main"); } // This is the App type's Finalize method ~App() { // For demonstration purposes, have the CLR's // Finalizer thread attempt to lock the object. // NOTE: Since the Main thread owns the lock, // the Finalizer thread is deadlocked! lock (this) { // Pretend to do something in here... } } }
3. 另一个deadlock的例子
A deadlock will only occur if you have more than one lock. You need a situation where both threads hold a resource that the other needs (which means there has to be a least two resources, and the two threads have to attempt to acquire them in a different order)
So a simple example:
// thread 1
lock(typeof(int)){
Thread.Sleep(1000);
lock(typeof(float)){
Console.WriteLine("Thread 1 got both locks");
}
}
// thread 2
lock(typeof(float)){
Thread.Sleep(1000);
lock(typeof(int)){
Console.WriteLine("Thread 2 got both locks");
}
}
Assuming both threads are started within a second of each others, they will both have time to grab
the first lock before anyone gets to the inner lock.
Without the Sleep() call, one of the threads would most likely have time to get and release both locks before the other thread even got started.
参考:http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx
http://msdn.microsoft.com/en-us/magazine/cc188793.aspx
http://stackoverflow.com/questions/894037/sample-code-to-illustrate-a-deadlock-by-using-lockthis