Part 95 to 96 Deadlock in a multithreaded program
Part 95 Deadlock in a multithreaded program
class Program { static void Main(string[] args) { Console.WriteLine("main start"); Account a1 = new Account(001,10000); Account a2 = new Account(002,20000); AccountManager m1 = new AccountManager(a1,a2,5000); Thread t1 = new Thread(m1.Transfer); t1.Name = "t1"; AccountManager m2 = new AccountManager(a2, a1, 3000); Thread t2 = new Thread(m2.Transfer); t2.Name = "t2"; t1.Start(); t2.Start(); t1.Join(); t2.Join(); Console.WriteLine("main end"); } } class Account { public int ID { get; set; } public double Balance { get; set; } public Account(int id, double balance) { this.ID = id; this.Balance = balance; } public void WithDraw(double amount) { Balance -= amount; } public void Deposit(double amount) { Balance += amount; } } class AccountManager { public Account FromAccount { get; set; } public Account ToAccount { get; set; } public double AmountToTransfer { get; set; } public AccountManager(Account from,Account to,double amountToTransfer) { this.FromAccount = from; this.ToAccount = to; this.AmountToTransfer = amountToTransfer; } public void Transfer() { Console.WriteLine(Thread.CurrentThread.Name+"try to acquire lock on"+FromAccount.ID.ToString()); lock (FromAccount) { Console.WriteLine(Thread.CurrentThread.Name+" acquired lock on "+FromAccount.ID.ToString()); Console.WriteLine(Thread.CurrentThread.Name+" suspended for 1 second"); Thread.Sleep(1000); Console.WriteLine(Thread.CurrentThread.Name+"back in action and try to acquire lock on" +ToAccount.ID.ToString()); lock (ToAccount) { Console.WriteLine("this code will not execute"); FromAccount.WithDraw(AmountToTransfer); ToAccount.Deposit(AmountToTransfer); } } } }
Part 96 How to resolve a deadlock in a multithreaded program
static void Main(string[] args) { Console.WriteLine("main start"); Account a1 = new Account(101,10000); Account a2 = new Account(102,20000); AccountManager m1 = new AccountManager(a1,a2,5000); Thread t1 = new Thread(m1.Transfer); t1.Name = "t1"; AccountManager m2 = new AccountManager(a2, a1, 3000); Thread t2 = new Thread(m2.Transfer); t2.Name = "t2"; t1.Start(); t2.Start(); t1.Join(); t2.Join(); Console.WriteLine("main end"); } } class Account { public int ID { get; set; } public double Balance { get; set; } public Account(int id, double balance) { this.ID = id; this.Balance = balance; } public void WithDraw(double amount) { Balance -= amount; } public void Deposit(double amount) { Balance += amount; } } class AccountManager { public Account FromAccount { get; set; } public Account ToAccount { get; set; } public double AmountToTransfer { get; set; } public AccountManager(Account from,Account to,double amountToTransfer) { this.FromAccount = from; this.ToAccount = to; this.AmountToTransfer = amountToTransfer; } public void Transfer() { object _lock1, _lock2; if(FromAccount.ID<ToAccount.ID) { _lock1 = FromAccount; _lock2 = ToAccount; } else { _lock1 = ToAccount; _lock2 = FromAccount; } Console.WriteLine(Thread.CurrentThread.Name+"try to acquire lock on "+((Account)_lock1).ID.ToString()); lock (_lock1) { Console.WriteLine(Thread.CurrentThread.Name + " acquired lock on " + ((Account)_lock1).ID.ToString()); Console.WriteLine(Thread.CurrentThread.Name+" suspended for 1 second"); Thread.Sleep(1000); Console.WriteLine(Thread.CurrentThread.Name + "back in action and try to acquire lock on " + ((Account)_lock2).ID.ToString()); lock (_lock2) { Console.WriteLine(Thread.CurrentThread.Name + " acquired lock on " + ((Account)_lock2).ID.ToString()); FromAccount.WithDraw(AmountToTransfer); ToAccount.Deposit(AmountToTransfer); Console.WriteLine(Thread.CurrentThread.Name+" Transferd "+AmountToTransfer.ToString()+" from "+FromAccount.ID.ToString()+" to "+ToAccount.ID.ToString()); } } }