2009-02-09 141 views
39

死锁很难找到,非常不舒服。什么是死锁的常见原因?

如何在我的代码中找到死锁的错误源?有没有“僵局模式”?

在我的特殊情况下,它处理数据库,但是这个问题对每个死锁都是开放的。

+1

注:它的“僵局”而不是“死锁”。一个词。 – 2009-02-09 14:30:37

+0

你是在谈论数据库死锁或者有关C#/ Java等的死锁吗? – SQLMenace 2009-02-09 14:23:00

回答

28

更新:此最近的MSDN文章,Tools And Techniques to Identify Concurrency Issues,也可能会感兴趣


斯蒂芬Toub MSDN文章Deadlock monitor各国需要以下四个条件发生死锁:

  • 数量有限的特定资源。对于C#中的监视器(使用lock关键字时使用的内容),由于监视器是互斥锁(意味着一次只能有一个线程可以拥有监视器),因此此限制数为1。

  • 能够保存一个资源并请求另一个资源。在C#,这类似于锁定一个物体上,然后释放第一锁,例如之前锁定在另一:


lock(a) 
{ 
... 
    lock(b) 
    { 
      ... 
    } 
} 
  • 没有抢占能力。在C#中,这意味着一个线程不能强制另一个线程释放锁。

  • 循环等待条件。这意味着有一个线程循环,每个线程都在等待下一个线程释放资源,然后才能继续。

他继续解释说,避免死锁的方法是避免(或阻止)条件四。

Joe Duffy discusses several techniques 用于避免并检测死锁, 包括一个被称为锁找平。 在锁定级别中,锁被指定为 数值,并且线程必须获取的锁具有比其已获取的锁具有更高的 数字的锁。这可以防止循环的可能性。这也是 在 今天典型的软件应用, 和一个失败锁定水平 每个锁采购邀请 死锁通常很难做好。

1

典型的情况是不匹配的更新计划(表不总是按照相同的顺序更新)。然而,在高处理量下,发生死锁并不罕见。

我倾向于接受死锁作为生活中的事实,它会在某一天发生,所以我让我的DAL准备处理并重试死锁操作。

4

是 - 进程尝试以随机顺序获取资源时发生死锁。如果您的所有进程都尝试以相同的顺序获取相同的资源,那么死锁的可能性会大大降低,如果不能消除的话。

当然,这并不总是容易安排......

12

经典的僵局的情况是一个持有锁X和想要获取锁Y,而B是持有锁Y和想要获取锁X 。既然两者都不能完成他们正在尝试做的事情,最终会永远等待(除非使用超时)。

在这种情况下,如果A和B以相同顺序获取锁,可以避免死锁。

8

确保所有事务以相同顺序影响表是避免最常见死锁的关键。

例如:

事务A

UPDATE Table A SET Foo = 'Bar' 
UPDATE Table B SET Bar = 'Foo' 

事务B

UPDATE Table B SET Bar = 'Foo' 
UPDATE Table A SET Foo = 'Bar' 

这是极有可能导致死锁作为事务A取得锁定在表A上,事务处理B在表B上获得锁定,因此它们都不会为其第二个命令获得锁定,直到另一个完成。

所有其他形式的死锁通常是由于高强度的使用和SQL Server在内部分配资源时发生死锁而引起的。

8

据我所知没有任何死锁模式(以及1​​2年的大量多线程交易应用程序)。但是TimedLock类对寻找存在于代码中的死锁没有大量返工有很大的帮助。

http://www.randomtree.org/eric/techblog/archives/2004/10/multithreading_is_hard.html

基本上,(在DOTNET/C#),你查找/替换所有的 “锁(XXX)” 语句以 “使用TimedLock.Lock(XXX)”

如果死锁检测过(无法在指定的超时时间内获得锁定,默认为10秒),则抛出异常。我的本地版本也立即记录堆栈跟踪。走上堆栈跟踪(最好使用行号进行调试构建),您将立即看到在失败点保存了哪些锁,以及它试图获取哪个锁。

在dotnet 1.1中,在所描述的死锁情况下,幸运的是所有被锁定的线程都会在同一时间抛出异常。所以你会得到2+栈跟踪和解决问题所需的所有信息。 (2。0+可能已经改变的线程模型内部够不得到这样的运气,我不知道)

1

(根据我的观察不科学)DB死锁情况非常简单,最常见的:

  • 两进程读取数据(例如数据库记录),都获取相关资源上的共享锁(通常是数据库页面),
  • 两者都尝试进行更新,尝试将其锁升级为独占锁 - 瞧,死锁。

如果读取后面跟有更新,则可以通过指定“FOR UPDATE”子句(或类似的,取决于特定的RDBMS)来避免这种情况。通过这种方式,流程从一开始就获得排它锁定,使上述情况变得不可能。

2

我推荐阅读Herb Sutter这篇文章。它解释了死锁问题背后的原因,并提出了解决这个问题的框架this article

1

出现两个进程每个都等待其他进程完成的情况之前,结果都是程序挂起。其最多的多任务和clint /服务器。

0

死锁主要发生在存在多个从属锁的情况下。在一个线程中,另一个线程试图以相反的顺序锁定互斥体。应该注意使用互斥锁来避免死锁。

解锁后务必完成操作。如果您有多个锁,例如访问订单是ABC,则发布订单也应该是ABC。

0

在我上一个项目中,我遇到了SQL Server数据库中的死锁问题。找到原因的问题是,我的软件和第三方软件正在使用相同的数据库并且正在使用相同的表格。很难找出导致僵局的原因。我最终编写了一个sql查询来找出哪些进程导致了哪些sql语句导致了死锁。你可以在这里找到这样的语句:Deadlocks on SQL-Server

相关问题