Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Part 96 - How to resolve a deadlock in a multithreaded program

Suggested Videos 
Part 93 - Protecting shared resources from concurrent access in multithreading
Part 94 - Difference between Monitor and lock in C#
Part 95 - Deadlock in a multithreaded program



In this video we will discuss, resolving a deadlock in a multithreaded program. There are several techniques to avoid and resolve deadlocks. For example
1. Acquiring locks in a specific defined order
2. Mutex class
3. Monitor.TryEnter() method



In this video, we will discuss, acquiring locks in a specific defined order to resolve a deadlock. We will be working with the same example that we worked with in Part 95

Sample program code used in the demo.
using System;
using System.Threading;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Main Started");
        Account accountA = new Account(101, 5000);
        Account accountB = new Account(102, 3000);

        AccountManager accountManagerA =
            new AccountManager(accountA, accountB, 1000);
        Thread T1 = new Thread(accountManagerA.Transfer);
        T1.Name = "T1";

        AccountManager accountManagerB =
            new AccountManager(accountB, accountA, 2000);
        Thread T2 = new Thread(accountManagerB.Transfer);
        T2.Name = "T2";

        T1.Start();
        T2.Start();

        T1.Join();
        T2.Join();
        Console.WriteLine("Main Completed");
    }
}

public class Account
{
    double _balance;
    int _id;

    public Account(int id, double balance)
    {
        this._id = id;
        this._balance = balance;
    }

    public int ID
    {
        get
        {
            return _id;
        }
    }

    public void Withdraw(double amount)
    {
        _balance -= amount;
    }

    public void Deposit(double amount)
    {
        _balance += amount;
    }
}

public class AccountManager
{
    Account _fromAccount;
    Account _toAccount;
    double _amountToTransfer;

    public AccountManager(Account fromAccount, Account toAccount, double amountToTransfer)
    {
        this._fromAccount = fromAccount;
        this._toAccount = toAccount;
        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
            + " trying 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 trying 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 + " Transfered "
                    + _amountToTransfer.ToString() + " from "
                    + _fromAccount.ID.ToString() + " to "
                    + _toAccount.ID.ToString());
            }
        }
    }
}

2 comments:

  1. please give sample for using Mutex Object

    ReplyDelete
  2. sir kudvenkat i do have a question ,we can also fix this using private static readonly object oo = new object();
    public void Transfer()
    {
    lock (oo)
    {
    Thread.Sleep(1000);
    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 trying to acquire lock on "
    + _fromAccount.ID.ToString());

    lock (_toAccount)
    {
    Console.WriteLine(Thread.CurrentThread.Name
    + " acquired lock on "
    + _toAccount.ID.ToString());

    _fromAccount.Withdraw(_amountToTransfer);
    _toAccount.Deposit(_amountToTransfer);

    Console.WriteLine(Thread.CurrentThread.Name + " Transfered "
    + _amountToTransfer.ToString() + " from "
    + _fromAccount.ID.ToString() + " to "
    + _toAccount.ID.ToString());
    }
    }
    }
    }
    }

    ReplyDelete

It would be great if you can help share these free resources