编程中出现死锁问题的常见程度如何?

i_l*_*eys 4 deadlock

我用多种语言编程,但我不知道代码中的死锁.

我认为这意味着它不会发生.

这是否经常发生(在编程中,而不是在数据库中)足够我应该关注它?

djn*_*jna 14

如果两个条件成立,则可能出现死锁:你有多个theads,他们争夺多个资源.

你写多线程代码?您可以通过启动自己的线程来显式地执行此操作,或者您可以在一个框架中工作,其中线程是在您的视线之外创建的,因此您在多个线程中运行而无需在代码中看到它.

一个例子:Java Servlet API.你编写了一个servlet或JSP.您部署到应用程序服务器.有几个用户访问了您的网站,因此也访问了您的servlet.服务器可能每个用户都有一个线程.

现在考虑如果在为请求提供服务时需要获取某些资源会发生什么:

if ( user Is Important ){
     getResourceA();
}

getResourceB();

if (today is Thursday ) {
    getResourceA();
} 


// some more code

releaseResourceA();
releaseResoruceB();
Run Code Online (Sandbox Code Playgroud)

在上面的设计示例中,考虑一个重要用户的请求到达时星期四会发生什么,并且或多或少同时发生不重要用户的请求.

重要用户的线程获得Resoruce A并且想要B.不太重要的用户获得资源B并且想要A.也不会释放他们已经拥有的资源...死锁.

如果您正在编写明确使用同步的代码,这实际上很容易发生.最常见的是,我发现在使用数据库时会发生这种情况,幸运的是,数据库通常会有死锁检测,因此我们可以找出我们犯了什么错误.

防止僵局:

  1. 以明确定义的顺序获取资源.在最后的示例中,如果资源A总是在资源B之前获得,则不会发生死锁.
  2. 如果可能,请使用超时,以便您不必无休止地等待资源.这将允许您检测争用并应用防御1.


Jon*_*eet 9

很难想象它在现实中发生的频率(在生产代码中?在开发中?)并且无论如何都不会真正了解有多少代码容易受到攻击.(通常情况下,僵局只会在非常特殊的情况下发生.)

我见过几次,虽然最近看到的是Oracle驱动程序(根本不在数据库中),因为终结器在另一个线程试图获取连接的同时运行.幸运的是,我发现了另一个让我避免终结器运行的错误......

基本上死锁几乎总是由于试图获得一个锁(B)同时持有另一个锁(A)而另一个螺纹完全相同而反之亦然.如果一个线程正在等待B被释放,并且持有B的线程正在等待A被释放,则两个线程都不愿意让另一个继续.

确保始终以相同的顺序获取锁(并以相反的顺序释放它们),并且在大多数情况下应该能够避免死锁.

有些奇怪的情况你没有直接拥有两把锁,但这是基本原理.例如,在.NET中,您可以使用Control.Invoke工作线程来更新UI线程上的UI.现在Invoke等待更新处理后再继续.假设您的后台线程持有锁更新需要...再次,工作线程正在等待UI线程,但UI线程无法继续,因为工作线程持有锁.再次陷入僵局.

这是一种需要注意的模式.如果你确定只锁定你需要的地方,锁定你可以逃脱的一段时间,并记录所有代码的线程安全和锁定策略,你应该能够避免死锁.但是,与所有线程主题一样,说起来容易做起来难.

  • 可悲的是,没有:-(在一些编程模型中,很容易发生在Web应用程序中. (3认同)