什么是僵局?

bmu*_*976 143 concurrency multithreading deadlock locking

编写多线程应用程序时,遇到的最常见问题之一是死锁.

我对社区的问题是:

  1. 什么是僵局?

  2. 你怎么发现它们?

  3. 你处理它们吗?

  4. 最后,你如何防止它们发生?

Kei*_*ith 190

当多个进程试图同时访问同一资源时.

一个过程失败,必须等待另一个完成.

一个死锁时,等待的过程中仍保存到另一个资源,它所收到的第一需要,可以完成发生.

那么,一个例子:

资源A和资源B由进程X和进程Y使用

  • X开始使用A.
  • X和Y尝试开始使用B.
  • Y'赢'并获得B优先
  • 现在Y需要使用A.
  • A被X锁定,等待Y.

避免死锁的最佳方法是避免以这种方式跨进程.减少尽可能多地锁定任何东西的需要.

在数据库中,避免在单个事务中对不同的表进行大量更改,避免触发器并尽可能切换到optimistic/dirty/nolock读取.

  • 我在这里使用流程作为概括,而不是特别是OS流程.这些可能是线程,但也可能是完全不同的应用程序或数据库连接.模式是一样的. (7认同)
  • @rickyProgrammer不,这只是一个常规的锁定等待,虽然差异有点学术性.B等待慢A是锁,B等待A等待B是死锁. (2认同)
  • @rickyProgrammer这是一个锁定,无论你等待多久都不会自由,因为循环队列. (2认同)

Lev*_*glu 118

让我解释一下犯罪电影中僵局情况的现实世界(实际上不是真实的).想象一下,一名罪犯挟持人质,反对这一点,警察还拥有一名人质,他是罪犯的朋友.在这种情况下,如果警察不让他的朋友放手,犯罪者就不会让劫持人质.除非犯罪分子释放人质,警察也不会让犯罪的朋友放手.这是一个无休止的不值得信任的局面,因为双方都坚持彼此迈出的第一步.

犯罪与警察现场

在此输入图像描述

简单地说,当两个线程需要两个不同的资源并且每个资源都拥有另一个需要的资源锁时,它就是一个死锁.

死锁的另一个高级解释:破碎的心

你和一个女孩约会,争吵后的一天,双方都心碎了,等待着我对不起,而且我错过了你的电话.在这种情况下,当且仅当其中一方收到来自另一方的I-am-sorry电话,双方都希望相互通信.因为每个都不会开始通信并且在被动状态下等待,所以两者都将等待另一个开始通信,最终处于死锁状态.

  • 现实生活中的另一个例子可能是四辆汽车同时在四个方向上穿越两条相等的道路。每个人都需要从右侧让路到汽车上,所以没有人可以前进。 (2认同)

Mat*_*son 34

只有当您有两个或更多可以同时获取的锁并且它们以不同的顺序被抓取时,才会发生死锁.

避免死锁的方法是:

  • 避免锁(如果可能的话),
  • 避免拥有多个锁
  • 总是以相同的顺序取锁.


Var*_*run 19

要定义死锁,首先我要定义进程.

过程 :我们知道过程只不过是program执行过程.

资源 :执行程序进程需要一些资源.资源类别可能包括内存,打印机,CPU,打开文件,磁带驱动器,CD-ROM等.

死锁 :死锁是两个或多个进程持有某些资源并尝试获取更多资源的情况或条件,并且在完成执行之前它们无法释放资源.

死锁情况或情况

在此输入图像描述

在上图中,有两个过程P1p2,并且有两个资源R1R2.

资源R1被分配给进程P1,资源R2被分配给进程p2.要完成进程P1的执行需要资源R2,所以P1请求R2,但R2已经分配给P2.

同样,Process P2完成其执行需要R1,但R1已经分配给P1.

除非完成执行,否则这两个进程都无法释放其资源.所以两人都在等待另一种资源,他们将永远等待.所以这是一个DEADLOCK条件.

为了发生死锁,必须有四个条件.

  1. 相互排斥 - 每个资源当前分配给一个进程或可用.(两个进程不能同时控制相同的资源或处于关键部分).
  2. 保持和等待 - 当前持有资源的进程可以请求新资源.
  3. 没有抢占 - 一旦进程拥有一个资源,它就不会被另一个进程或内核带走.
  4. 循环等待 - 每个进程都在等待获取另一个进程持有的资源.

在上图中满足所有这些条件.


17 *_* 26 8

当线程正在等待从未发生的事情时发生死锁.

通常情况下,当线程正在等待前一个所有者从未发布的互斥锁或信号量时,就会发生这种情况.

当你遇到涉及两个线程和两个锁的情况时,它经常发生:

Thread 1               Thread 2

Lock1->Lock();         Lock2->Lock();
WaitForLock2();        WaitForLock1();   <-- Oops!
Run Code Online (Sandbox Code Playgroud)

您通常会检测它们,因为您希望发生的事情永远不会发生,或者应用程序完全挂起.


onm*_*133 5

您可以看看死锁部分下的这篇精彩文章。它是用 C# 编写的,但对于其他平台来说,这个想法仍然是相同的。为了方便阅读,我在这里引用一下

当两个线程都等待另一个线程持有的资源,因此两个线程都无法继续时,就会发生死锁。说明这一点的最简单方法是使用两个锁:

object locker1 = new object();
object locker2 = new object();

new Thread (() => {
                    lock (locker1)
                    {
                      Thread.Sleep (1000);
                      lock (locker2);      // Deadlock
                    }
                  }).Start();
lock (locker2)
{
  Thread.Sleep (1000);
  lock (locker1);                          // Deadlock
}
Run Code Online (Sandbox Code Playgroud)