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

Part 95 - Deadlock in a multithreaded program

Suggested Videos 
Part 92 - Significance of Thread.Join and Thread.IsAlive functions
Part 93 - Protecting shared resources from concurrent access in multithreading
Part 94 - Difference between Monitor and lock in C#



In this video we will discuss, why and how a deadlock can occur in multithreading with an example.



Scenario when a deadlock can occur
Let's say we have 2 threads 
a) Thread 1
b) Thread 2

and 2 resources
a) Resource 1
b) Resource 2

Thread 1 has already acquired a lock on Resource 1 and wants to acquire a lock on Resource 2. At the same time Thread 2 has already acquired a lock on Resource 2 and wants to acquire a lock on Resource 1. Two threads never give up their locks, hence a deadlock.

Deadlock example

Example 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()
    {
        Console.WriteLine(Thread.CurrentThread.Name
            + " trying 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 trying to acquire lock on "
                + _toAccount.ID.ToString());

            lock (_toAccount)
            {
                _fromAccount.Withdraw(_amountToTransfer);
                _toAccount.Deposit(_amountToTransfer);
            }
        }
    }
}

2 comments:

  1. hi kudvenkat sir.. why we cant have only one lock in transfer.


    public void Transfer()
    {
    object _lock = new object();// added only one lock
    Console.WriteLine(Thread.CurrentThread.Name + " trying to acquire lock on " + _fromAccount.ID.ToString());
    lock (_lock)
    {
    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 " + _toAccount.ID.ToString());

    //lock (_toAccount)
    //{
    _fromAccount.Withdraw(_amountToTransfer);
    _toAccount.Deposit(_amountToTransfer);
    //}

    }
    Console.WriteLine(Thread.CurrentThread.Name + "Completed The Transfer");
    }

    ReplyDelete
  2. Lock is applicable to only one resource at a time

    ReplyDelete

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