Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dead lock in Multithreading

I was trying to create an example for deadlock. I tried the following code. But instead of creating deadlock, it worked like charm. Help me in understanding why it didn't create a deadlock. What change in this code would create a deadlock?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ReferenceTypes
{
    class DeadLockExample
    {
        static int a;
        static int b;

        public static void Main(string[] args)
        {
            DeadLockExample.a = 20;
            DeadLockExample.b = 30;

            DeadLockExample d = new DeadLockExample();

            Thread tA = new Thread(new ThreadStart(d.MethodA));
            Thread tB = new Thread(new ThreadStart(d.MethodB));

            tA.Start();
            tB.Start();

            Console.ReadLine();
        }

        private void MethodA()
        {
            lock (this)
            {
                Console.WriteLine(a);
                Thread.Sleep(1000);
                Console.WriteLine(b);
            }
        }

        private void MethodB()
        {
            lock (this)
            {
                Console.WriteLine(b);
                Thread.Sleep(1000);
                Console.WriteLine(a);
            }
        }
     }
}
like image 352
SaravananArumugam Avatar asked Aug 19 '10 23:08

SaravananArumugam


3 Answers

As everyone else has said, two locks acquired in different orders, so that each is waiting on the other. I also changed one of the Sleep lengths to ensure a high probability of the deadlock occurring.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ReferenceTypes
{
    class DeadLockExample
    {
        static int a;
        static int b;

        static object lockedObjA = new object();
        static object lockedObjB = new object();

        public static void Main(string[] args)
        {
            DeadLockExample.a = 20;
            DeadLockExample.b = 30;

            DeadLockExample d = new DeadLockExample();

            Thread tA = new Thread(new ThreadStart(d.MethodA));
            Thread tB = new Thread(new ThreadStart(d.MethodB));

            tA.Start();
            tB.Start();

            Console.ReadLine();
        }

        private void MethodA()
        {
            lock (DeadLockExample.lockedObjA)
            {
                Console.WriteLine(a);
                Thread.Sleep(1200);

                lock (DeadLockExample.lockedObjB) {
                    Console.WriteLine(b);
                }
            }
        }

        private void MethodB()
        {
            lock (DeadLockExample.lockedObjB)
            {
                Console.WriteLine(b);
                Thread.Sleep(1000);

                lock (DeadLockExample.lockedObjA) {
                    Console.WriteLine(a);
                }
            }
        }
     }
}
like image 126
quentin-starin Avatar answered Sep 27 '22 16:09

quentin-starin


2 locks, 2 threads.

Thread A takes lock A, sleeps and then tries to take lock B. Thread B takes lock B, sleeps and then tries to take lock A, equals a Deadlock.

[Thread A has to sleep long enough so that thread B takes lock B before thread A attempts to acquire it]

like image 34
Mitch Wheat Avatar answered Sep 27 '22 16:09

Mitch Wheat


Here are 3 different ways you can cause a deadlock. This list is not exhaustive.

Call a blocking method from within a lock section.

In this example thread A acquires a lock and then immediately calls a blocking method while at the same time thread B attempts to acquire the same lock, but gets hung because thread A is waiting for thread B to signal the event before it will release the lock.

public class Example
{
  ManualResetEvent m_Event = new ManualResetEvent(false);

  void ThreadA()
  {
    lock (this)
    {
      m_Event.WaitOne();
    }
  }

  void ThreadB()
  {
    lock (this)
    {
      m_Event.Set();
    }
  }
}

Acquire two locks out of order.

No explanation is needed here since this is a well known problem.

public class Example
{
  private object m_LockObjectA = new object();
  private object m_LockObjectB = new Object();

  void ThreadA()
  {
    lock (m_LockObjectA) lock (m_LockObjectB) { }
  }

  void ThreadB()
  {
    lock (m_LockObjectB) lock (m_LockObjectA) { }
  }
}

The lock-free deadlock.

This is one my favorite illustrations of a deadlock because no lock or blocking method is involved. The subtlety of the problem is enough to confound even those who are familiar with threading. The issue here is related to the absence of memory barriers. Thread A waits for thread B to set the signal flag while at the same time thread B waits for thread A to reset it all the while neither thread is seeing the changes the other is making because the compiler, JIT, and hardware are free to optimize the reads and writes of the flag in manner that is non-intuitive.

public class Example
{
  private bool m_Signal = false;

  void ThreadA()
  {
    while (!m_Signal);
    m_Signal = false;
  }

  void ThreadB()
  {
    m_Signal = true;
    while (m_Signal);
  }
}
like image 35
Brian Gideon Avatar answered Sep 27 '22 17:09

Brian Gideon