HI WELCOME TO SIRING

Deadlock in a multithreaded program in C#

Leave a Comment
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(1015000);
        Account accountB = new Account(1023000);

        AccountManager accountManagerA = new
            AccountManager(accountAaccountB1000);
        Thread T1 = new Thread(accountManagerA.Transfer);
        T1.Name = "T1";

        AccountManager accountManagerB = new
            AccountManager(accountBaccountA2000);
        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 iddouble 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 toAccountdouble 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);
            }
        }
    }
}

0 comments:

Post a Comment

Note: only a member of this blog may post a comment.