我是多线程编程的新手 如果一个线程必须从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();
}
}
}
}
我修改了代码以防止崩溃
答案 0 :(得分:9)
假设您吞下足够的异常甚至让代码运行,当操作按以下顺序执行时,它可能会死锁:
t2.Resume() //on t1
t1.Resume() //on t2
t2.Suspend() //on t2
t1.Suspend() //on t1
结果两个线程都保持挂起状态。
这通常不是处理线程同步的方法。就个人而言,我从未在线程上使用Resume
或Suspend
。
您应该阅读.NET中的同步机制,从lock
语句开始。我推荐来自Albahari free chapters的c# in a Nutshell:
答案 1 :(得分:1)
除了Rotem已经解释过的情况之外,您正在尝试使用多线程而不允许多线程发生。如果您尝试以彼此独占的方式同步两个线程,只运行其中一个线程,那么您实际上就放弃了使用多线程的所有好处。相反,您在线程管理和同步方面增加了巨大的开销。因此,您的解决方案(如果您正常工作)很可能比这样的简单单线程实现慢得多:
for (int count = 0; count < 1000; count++)
{
Console.WriteLine("Th2" + ((2 * count2) + 1));
Console.WriteLine("Th1" + (2 * count1));
}
话虽如此,如果您想以某种方式“修复”您的解决方案,那么您必须确保以原子方式执行Suspend
和Resume
操作,以便其他线程不能在指令之间执行。您可以通过在执行期间锁定对象来完成此操作。