What is a deadlock?编写多线程应用程序时,遇到的最常见问题之一是死锁。 我对社区的问题是: 什么是僵局? 您如何检测到它们? 你会处理吗? 最后,您如何防止它们发生? 当多个进程尝试同时访问同一资源时,将发生锁定。 一个过程失败了,必须等待另一个过程完成。 当等待进程仍保留第一个需要完成的另一个资源时,就会发生死锁。 举个例子: 资源A和资源B由流程X和Y使用
避免死锁的最佳方法是避免进程以这种方式交叉。尽可能减少锁定任何东西的需要。 在数据库中,请避免在单个事务中对不同表进行大量更改,避免使用触发器,并尽可能切换到乐观/脏/无锁读取。 让我解释一下犯罪电影中出现僵局的真实示例(不是真实示例)。想象一下,一个罪犯将人质扣为人质,而警察也将人质作为罪犯的朋友。在这种情况下,如果警察不让他的朋友放手,罪犯就不会放开人质。另外,除非罪犯释放人质,否则警察不会放任罪犯的朋友。这是一种无休止的不信任局面,因为双方都在坚持彼此的第一步。 犯罪与警察现场
简而言之,当两个线程需要两个不同的资源,并且每个线程都拥有另一个需要的资源锁时,这就是一个死锁。 僵局的另一个高级解释:破碎的心 您正在与一个女孩约会,吵架后的第二天,双方彼此伤心欲绝,正等着我对不起和我想念您的电话。在这种情况下,当且仅当其中一方收到对方的I-am-sorry呼叫时,双方才希望彼此通信。因为每个都不打算开始通信并在被动状态下等待,所以两个都将等待另一个开始通信,最终陷入僵局。 只有当您同时拥有两个或两个以上的锁并且以不同的顺序抓住它们时,才会发生死锁。 避免出现死锁的方法是:
要定义死锁,首先我要定义过程。
进程:众所周知,进程只是执行中的 资源:执行程序过程需要一些资源。资源类别可能包括内存,打印机,CPU,打开的文件,磁带驱动器,CD-ROM等。 死锁:当两个或多个进程持有一些资源并试图获取更多资源,并且直到完成执行后才能释放资源,这是一种情况或状况。 死锁情况或情况
在上图中,有两个过程P1和p2,有两个资源R1和R2。
资源R1被分配给进程P1,资源R2被分配给进程p2。 以相同的方式,进程P2完成其执行需要R1,但R1已分配给P1。 这两个进程只有在完成执行后才能释放资源。因此,两者都在等待其他资源,他们将永远等待。所以这是一个死锁条件。 为了使死锁发生,必须满足四个条件。 同时控制同一资源或处于关键地位 部分)。 以上条件均满足。 当线程正在等待永远不会发生的事情时,就会发生死锁。 通常,它发生在线程正在等待以前所有者从未释放过的互斥量或信号量时。 当您遇到涉及两个线程和两个锁的情况时,也经常发生这种情况:
通常,您检测到它们是因为您期望发生的事情永远不会发生,或者应用程序完全挂起。
死锁是OS中多处理/多编程问题中的常见问题。
最初,OS将R1分配给进程P1,将R2分配给进程P2。 一个小类比...
您可以在"死锁"部分中查看这些精彩的文章。它是用C#语言编写的,但对于其他平台来说,想法仍然相同。我在这里引用以方便阅读
当有一个循环的线程或进程链,每个线程或进程都拥有一个锁定的资源,并试图锁定该链中下一个元素所拥有的资源时,就会发生死锁。例如,两个分别持有锁A和锁B的线程都试图获取另一个锁。 当两个线程获得锁而阻止它们中的任何一个前进时,就会发生死锁。避免它们的最好方法是精心开发。许多嵌入式系统通过使用看门狗计时器(该计时器在系统挂起一定时间后会重置系统的计时器)来保护它们。 一个经典且非常简单的程序,用于了解死锁情况:-
当主线程调用Lazy.main时,它将检查类Lazy
这次,该类当前正在由另一个线程初始化。 死锁是系统的一种状态,其中没有单个进程/线程能够执行操作。正如其他人所提到的,死锁通常是以下情况的结果:每个进程/线程希望获得对已由另一个(甚至相同)进程/线程锁定的资源的锁定。 有多种方法可以找到它们并避免它们。一个人非常努力地思考和/或尝试了许多事情。但是,处理并行性非常困难,并且大多数(如果不是全部)人将无法完全避免问题。 如果您认真对待此类问题,则可以使用一些更正式的方法。我知道的最实用的方法是使用过程理论方法。在这里,您可以使用某种过程语言(例如CCS,CSP,ACP,mCRL2,LOTOS)对系统进行建模,并使用可用工具对死锁(以及可能还有其他一些属性)进行(建模)检查。使用的工具集示例包括FDR,mCRL2,CADP和Uppaal。一些勇敢的灵魂甚至可以通过使用纯粹的象征性方法来证明他们的系统没有死锁(定理证明;寻找Owicki-Gries)。 但是,这些形式化方法通常确实需要付出一些努力(例如,学习过程理论的基础知识)。但是我想这仅仅是这些问题很难解决的结果。
当不同进程请求的可用资源数量较少时,就会发生死锁。这意味着当可用资源的数量少于用户请求的数量时,该过程将进入等待状态。有时等待时间会增加,因此没有机会检查资源不足的问题。这种情况称为死锁。 尽管这是最常见的原因,但死锁不仅仅与锁一起发生。在C ++中,可以通过让每个线程在另一个对std :: thread对象上调用join()来创建具有两个线程且没有锁的死锁。
以上是一些很好的解释。希望这也可能有用:
在数据库中,当一个会话(例如ora)想要另一个会话持有的资源(例如数据),但是该会话(数据)也想要一个第一个会话(ora)持有的资源时。也可以涉及两个以上的会话,但想法是相同的。 谢谢, 当一个线程正在等待其他线程完成时发生死锁,反之亦然。
如何避免?
您如何检测到它?
参考:geeksforgeeks 互斥锁本质上是一个锁,它提供对共享资源的受保护的访问。在Linux下,线程互斥量数据类型为pthread_mutex_t。使用之前,请对其进行初始化。 要访问共享资源,您必须锁定互斥锁。如果互斥锁已处于锁定状态,则调用将阻塞线程,直到互斥锁解锁为止。访问共享资源完成后,您必须将其解锁。 总体而言,有一些未成文的基本原则:
|