[Turn] A simple C# deadlock program

Reprinted from: http://blog.csdn.net/hulihui/article/details/3319948 (but the original part is wrong, I have modified it)

 

 

Jeffrey Richter described a deadlock situation in "Windows Core Programming (5th Edition)": Assuming that both threads Thread1 and Thread2 need exclusive access to the mutually exclusive resources m_res1 and m_res2, the application mutex object Monitor enters before use (equivalent to Locked), Exit after use (equivalent to unlocking). Since two resources are involved, special attention needs to be paid to the order of locking. If the locking sequence of the two threads is different (Thread1 locks m_res2 first, Thread2 locks m_res1 first), deadlock is prone to occur. Based on this idea, the complete program code implemented by C# is given below:

class Program
{
    private static object m_res1 = new object();
    private static object m_res2 = new object();
    private static int m_count = 0;

    static void Main(string[] args)
    {
        Thread t1 = new Thread(Thread1);
        Thread t2 = new Thread(Thread2);

        t1.Start();
        t2.Start();

        while (true)
        {
            int preCount = m_count;
            Thread.Sleep(0); // Give up the CPU time slice of the current thread, Windows may schedule other threads
            if (preCount == m_count) // The data has not changed, indicating that the thread is not executing
            {
                Console.WriteLine("dead lock! count: {0}", m_count);
            }
        }           
    }

    private static void Thread1()
    {
        while (true)
        {
            Monitor.Enter(m_res2); // lock m_res2 first
            Monitor.Enter(m_res1); // lock m_res1 again

            m_count++;

            Monitor.Exit(m_res1); // There is no precedence for releasing locks
            Monitor.Exit(m_res2);
        }
    }

    private static void Thread2()
    {
        while (true)
        {
            Monitor.Enter(m_res1); // lock m_res1 first
            Monitor.Enter(m_res2);

            m_count++;

            Monitor.Exit(m_res1);
            Monitor.Exit(m_res2);
        }
    }
}

 When the above program is run, the deadlock phenomenon occurs when the count reaches about 300 (the author's machine). The reason is: if Thread1 locks m_res2 at the same time, and Thread2 obtains the lock of m_res1, then Thread1 cannot obtain the lock of m_res1, and of course Thread2 cannot obtain the lock of m_res2. Neither thread can continue, so the value of m_count does not change.

 

If the locking sequence of thread Thread1 is the same as thread Thread2, that is:

Monitor.Enter(m_res1);
 Monitor.Enter(m_res2);

At this time, there will be no deadlock situation: Thread1 locks m_res1 and applies for lock m_res2, and Thread2 locks m_res2 and applies for m_res1. Reason: Because when Thread2 locks m_res2, it either locks m_res1 first, or it is too late to release m_res2 when releasing m_res1. The first phenomenon is impossible, because Thread1 locks m_res1; the second phenomenon is to release the lock, and there is no immediate application for the lock. Therefore, there is no deadlock situation when the order is the same. (This sentence is very problematic, I can't understand it)

 

The solution is also: use the bool Monitor.TryEnter() method, try to lock and set a time upper bound. If it can't be locked, give up the lock and do other operations.

 

Summary: When multiple threads lock multiple resources, they must be in the same order.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327083502&siteId=291194637