C# Solving a Thread Deadlock

C# Code Snippets Thread deadlock
Share:

About

In this code snippet, we will take a look at thread deadlocks in C# and how to resolve them.

If you see this post I made about thread resource locking you will see why a thread would need to lock a resource to prevent other threads from using it. But when you start locking down resources you could potentially run into a deadlock.

A thread deadlock occurs in such a situation:

    1. Thread 1 acquires a lock on resource A.
    2. Thread 2 acquires a lock on resource B.
    3. Thread 1 needs resource B to complete its execution.
    4. Thread 2 needs resource A to complete its execution.
    5. Both threads are now waiting on each other to finish.

To resolve this deadlock we need to change our code in such a way:

    1. Thread 1 acquires a lock on resource A.
    2. Thread 2 tries to acquire a lock on resource A but fails because it’s already locked.
    3. Thread 1 acquires a lock on resource B and completes its execution. After that, the lock on A and B is released.
    4. Thread 2 acquires a lock on A.
    5. Thread 2 acquires a lock on B and completes its execution.

Basically what you have to do is make sure that you are locking resources in the same order in all the threads. This way when the first common resource is locked by one thread no other thread can continue executing and locking on any other common resource required by the first thread.

Let’s have a look at the code below to see how to resolve a deadlock.

Code:

using System;
using System.Threading;

namespace ThreadDeadlock
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass MC = new MyClass();

            //Make threads.
            Thread th1 = new Thread(() => MC.transferFromAToB(100));
            Thread th2 = new Thread(() => MC.transferFromBToA(100));

            //Start threads.
            th1.Start();
            th2.Start();
           
            Console.ReadLine();
        }
    }

    class MyClass
    {
        private int a;
        private int b;

        //lock objects.
        private Object aLock = new Object();
        private Object bLock = new Object();

        public MyClass()
        {
            a = 1000;
            b = 1000;
        }

        #region Deadlock Code

        
        public void transferFromAToB(int amount)
        {
            lock (aLock)
            {
                //Simulate computing time to get the value;
                Thread.Sleep(100);
                a = a - amount;
              
                lock (bLock)
                {
                    //Simulate computing time to get the value;
                    Thread.Sleep(100);
                    b = b + amount;
                }
            }

            Console.WriteLine(amount + " was transfered from A to B.");
        }

        public void transferFromBToA(int amount)
        {
            lock (bLock)
            {
                //Simulate computing time to get the value;
                Thread.Sleep(100);
                b = b - amount;

                lock (aLock)
                {
                    //Simulate computing time to get the value;
                    Thread.Sleep(100);
                    a = a + amount;
                }
            }

            Console.WriteLine(amount + " was transfered from B to A.");
        }
        

        #endregion

        #region Resolved deadlock Code
        /*
        public void transferFromAToB(int amount)
        {
            lock (aLock)
            {
                //Simulate computing time to get the value;
                Thread.Sleep(100);
                a = a - amount;
              
                lock (bLock)
                {
                    //Simulate computing time to get the value;
                    Thread.Sleep(100);
                    b = b + amount;
                }
            }
            Console.WriteLine(amount + " was transfered from A to B.");
        }
        public void transferFromBToA(int amount)
        {
            lock (aLock)
            {
                //Simulate computing time to get the value;
                Thread.Sleep(100);
                a = a + amount;          
                lock (bLock)
                {
                    //Simulate computing time to get the value;
                    Thread.Sleep(100);
                    b = b - amount;
                }
            }
            Console.WriteLine(amount + " was transfered from B to A.");
        }
        */
        #endregion
    }
}

Resulting output:

c# thread deadlock resulting output
Thread deadlock
c# thread deadlock solved resulting output
Thread deadlock resolved
Share:

Leave a Reply

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

The following GDPR rules must be read and accepted:
This form collects your name, email and content so that we can keep track of the comments placed on the website. For more info check our privacy policy where you will get more info on where, how and why we store your data.

Advertisment ad adsense adlogger