Monday, July 22, 2019

How to resolve a deadlock in a multithreaded program

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(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 fromAccountAccount toAccountdoubleamountToTransfer)
    {
        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());
            }
        }
    }
}

No comments:

Post a Comment

No String Argument Constructor/Factory Method to Deserialize From String Value

  In this short article, we will cover in-depth the   JsonMappingException: no String-argument constructor/factory method to deserialize fro...