Multi-Threading Deadlock Interview Questions C#.NET

Multi-Threading Deadlock Interview Questions and Answers C#.NET

In this article, I am going to discuss most frequently asked Multi-Threading Deadlock Interview Questions and Answers on C#.NET.

Explain 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 Thread 1 and Thread 2

And 2 resources Resource 1 and 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. 

Multi-Threading Deadlock Interview Questions and Answers C#.NET
 

Example code used in the demo
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);
            }
        }
    }
}
How to resolve 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 

Let us discuss, acquiring locks in a specific defined order to resolve a deadlock

Example:

What is AutoResetEvent and how it is different from ManualResetEvent?

The AutoResetEvent is used when we have to unlock only one single thread from several waiting blocked threads.

Below are differences from ManualResetEvent.

  1. ManualResetEvent is used for unblocks many threads simultaneously. But AutoResetEvent is used for unblocks only one single thread.
  2. You have to call Reset() method manually after calling Set() method to reset the ManualResetEvent. But AutoResetEvent Set() method automatically calls the Reset() method.
What is the Semaphore?

Semaphores are used when we have to restrict how many threads can enter a critical region. Semaphore is simply a int32 variable maintained by the kernel. We have initialize the Semaphore variable we specify the count how many threads can enter into critical region at a time. A thread waiting on a semaphore blocks when the semaphore is 0 and unblocks when the semaphore is greater than 0.

When we create instantiate a semaphore object, we have to provide two parameters in the constructor. First one is the InitialCount and second one is MaximumCount.

MaximumCount denotes the maximum number of threads that can enter concurrently.

InitialCount denotes the initial number of threads which can enter the Semaphore directly.

Threads enter the semaphore by calling the WaitOne method and release the semaphore by calling the Release method. You can release multiple threads by passing the count in the Release method. By default Release method takes one and only release one thread.

What is Mutex and how it is different from another Synchronization mechanisms?

Mutex works similarly like AutoResetEvent and releases only one waiting thread at a time.

In the AutoResetEvent any thread can call the Set() method and unblock a waiting thread. But Mutex object remembers the thread which got the Mutex object and only that thread can release the Mutex.

Mutex object auto record the thread id which got the Mutex object and when a user calls the ReleaseMutex() method for releasing a Mutex object, it internally checks whether the releasing thread is same as the thread which got the Mutex object if yes, then only it releases the Mutex object else it throws an exception.

Mutex famous example:

The mutex is like a key to a toilet. One person can have the key – occupy the toilet – at the time. When finished, the person gives (frees) the key to the next person in the queue.

What is the Race condition?

A race condition happens when two or more threads want to update shared data at the same time.

What is the volatile keyword?

Volatile is used for serializing the access of variable without using the synchronization primitives. You can use volatile with below types:

  1. References type
  2. Pointer types
  3. Values types
  4. IntPtr

public volatile int number;

How can you share data between multiple threads?

There are two ways to share data between multiple threads:

Concurrent collection classes

Using Synchronization Primitives

What are Concurrent Collection Classes?

.NET framework class library comes with Concurrent collection classes so that multiple threads can share collection data between them without using synchronization primitives.

There are four types of Concurrent classes.

  1. ConcurrentQueue
  2. ConcurrentStack
  3. ConcurrentDictionary
  4. ConcurrentBag
What is synchronization and why it is important?

We use multiple threads to improve the performance of our application. When multiple threads shares data between there is a chance of data corruption. When one thread is writing to the variable another thread is reading the same variable at the same time there is a chance of reading corrupt data.

To stop the dirty reads we use synchronization primitives.

Can you count some names of Synchronization primitives?
  1. Monitor
  2. Mutex
  3. Spinlock
  4. ReaderWriterLock
  5. Semaphore
  6. AutoResetEvent
  7. ManualResetEvent
  8. Interlocked
  9. CountDownEvent
  10. Barrier
What are four necessary conditions for Deadlock?

Mutual Exclusion: Resources involved must be unshareable between multiple threads.

Hold and Wait: Threads hold the resources they have allocated and waiting for the resources they want.

No pre-emption: If thread locks the resource, other threads cannot take the resource until the thread releases it.

Circular Wait: A circular chain must exist in which each thread waiting for other threads to release resources.

What is LiveLock?

A livelock is very similar to deadlock except for involved threads states are continually changing their state but still, they cannot complete their work.

A real-world example of livelock occurs when two people meet in a narrow corridor, and each tries to be polite by moving aside to let the other pass, but they end up swaying from side to side without making any progress because they both repeatedly move the same way at the same time.

SUMMARY

In this article, I try to explain most frequently asked Multi-Threading Deadlock Questions and Answers on C#.NET. I hope this article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *