为什么在下面给出的多线程程序中存在死锁

时间:2014-06-02 12:21:40

标签: c# multithreading c#-4.0

我是多线程编程的新手 如果一个线程必须从0到1000打印奇数而其他线程必须打印偶数,这种方法中死锁的原因是什么?

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

namespace ConsoleApplication9
{
    class Program
    {
        static int count1;
        static int count2;
        static Thread t1, t2;
        static void MulOf2()
        {
            while (count1 < 1000)
            {
                Console.Write("Th1" + (2 * count1) + "\n");
                count1++;
                if (t2.IsBackground)
                {
                    if (!t2.IsAlive)
                    {
                        t2.Resume();
                    }
                }
                t1.Suspend();
            }
        }
        static void Main(string[] args)
        {

            t1 = new Thread(MulOf2);
            t2 = new Thread(MulOf2Plus1);
            t1.Start();
            t2.Start();
        } 

         static void MulOf2Plus1()
        {
            while (count2 < 1000)
            {
                Console.Write("Th2" + ((2 * count2) + 1) + "\n");
                count2++;
                if (t1.IsBackground)
                {
                    if (!t1.IsAlive)
                    {
                        t1.Resume();
                    }
                }
                t2.Suspend();
            }
        }
    }
}

我修改了代码以防止崩溃

2 个答案:

答案 0 :(得分:9)

假设您吞下足够的异常甚至让代码运行,当操作按以下顺序执行时,它可能会死锁:

t2.Resume() //on t1
t1.Resume() //on t2
t2.Suspend() //on t2
t1.Suspend() //on t1

结果两个线程都保持挂起状态。

这通常不是处理线程同步的方法。就个人而言,我从未在线程上使用ResumeSuspend

您应该阅读.NET中的同步机制,从lock语句开始。我推荐来自Albahari free chaptersc# in a Nutshell

答案 1 :(得分:1)

除了Rotem已经解释过的情况之外,您正在尝试使用多线程而不允许多线程发生。如果您尝试以彼此独占的方式同步两个线程,只运行其中一个线程,那么您实际上就放弃了使用多线程的所有好处。相反,您在线程管理同步方面增加了巨大的开销。因此,您的解决方案(如果您正常工作)很可能比这样的简单单线程实现慢得多:

for (int count = 0; count < 1000; count++)
{
    Console.WriteLine("Th2" + ((2 * count2) + 1));
    Console.WriteLine("Th1" + (2 * count1));
}

话虽如此,如果您想以某种方式“修复”您的解决方案,那么您必须确保以原子方式执行SuspendResume操作,以便其他线程不能在指令之间执行。您可以通过在执行期间锁定对象来完成此操作。