参考博文:
https://blog.csdn.net/hd12370/article/details/82814348
死锁是什么?
死锁是指多个线程在运行过程中,因为抢占资源而造成一种僵局。
比如:当线程A持有独占锁a,并尝试获取独占锁b的同时,线程B持有独占锁b,并尝试获取独占锁a的情况下,就会发生AB线程由于持有对方需要的锁,而发生阻塞,我们称为死锁。
例如:
class Program
{
static void Main(string[] args) {
DeadLockDemo deadLockDemo = new DeadLockDemo();
deadLockDemo.Test();
Console.ReadKey();
}
}
class DeadLockDemo
{
private readonly object locker1 = new object();
private readonly object locker2 = new object();
public void Test() {
Thread th1 = new Thread(Method1);
Thread th2 = new Thread(Method2);
th1.Start();
th2.Start();
}
void Method1() {
lock (locker1) {
try {
Thread.Sleep(10000);
} catch (Exception e) {
Console.WriteLine(e.StackTrace);
}
Console.WriteLine("线程a尝试获取locker2");
lock (locker2) {
Console.WriteLine("线程a已经获取locker2");
}
}
}
void Method2() {
lock (locker2) {
try {
Thread.Sleep(10000);
} catch (Exception e) {
Console.WriteLine(e.StackTrace);
}
Console.WriteLine("线程b尝试获取locker1");
lock (locker1) {
Console.WriteLine("线程b已经获取locker1");
}
}
}
}
线程b尝试获取String.class
线程a尝试获取integer.class
…
…
…
.
无限阻塞下去
在上面的例子中,由于已经不存在 线程a 持有 线程b需要的锁,而线程b持有线程a需要的锁的逻辑了,所以Demo顺利执行完毕。
死锁产生的原因?
互斥性:一个资源每次只能被一个线程使用
请求和保持条件:当进程因请求资源而阻塞s时,对已获得的资源保持不放
不剥夺原则:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完后自己释放
循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系
如何避免死锁?
资源一次性分配:一次性分配资源
只要一个资源得不到分配,也不给这个进程分配资源
可剥夺资源:即当某进程获得了部分资源,得不到其他资源,则释放已占有的资源
资源有序分分配:系统给每类资源赋予一个编号,每一个进程按标号递增的顺序请求资源,释放则相反。
上例死锁代码可以改为:
class Program {
static void Main(string[] args) {
DeadLockDemo deadLockDemo = new DeadLockDemo();
deadLockDemo.Test();
Console.ReadKey();
}
}
class DeadLockDemo
{
private readonly object locker1 = new object();
private readonly object locker2 = new object();
public void Test() {
Thread th1 = new Thread(Method1);
Thread th2= new Thread(Method2);
th1.Start();
th2.Start();
}
void Method1() {
lock (locker1) {
try {
Thread.Sleep(10000);
} catch (Exception e) {
Console.WriteLine(e.StackTrace);
}
Console.WriteLine("线程a尝试获取locker2");
lock (locker2) {
Console.WriteLine("线程a已经获取locker2");
}
}
}
void Method2() {
lock (locker1) {
try {
Thread.Sleep(10000);
} catch (Exception e) {
Console.WriteLine(e.StackTrace);
}
Console.WriteLine("线程b尝试获取locker2");
lock (locker2) {
Console.WriteLine("线程b已经获取locker2");
}
}
}
}