提示,以防止java中的死锁

我正在学习java线程和死锁,我理解死锁的例子,但是我想知道是否有通用的规则来阻止它。

我的问题是,如果有规则或技巧,可以应用到Java中的源代码,以防止死锁? 如果是的话,你能解释一下如何实现它吗?

一些快速的小贴士

  • 不要使用multithreading(比如像Swing那样,要求所有东西都在EDT中完成)
  • 不要一次抓几把锁。 如果你这样做,总是以相同的顺序获得锁
  • locking时不要执行外部代码
  • 使用可中断的锁

封装,封装,封装! 也许你能用锁来犯的最危险的错误就是把你的锁暴露给世界(使之公开)。 如果你这样做,没有任何事情会发生,因为任何人都可以在没有对象知道的情况下获得锁(这也是为什么你不应该lockingthis )。 如果你保持你的锁私人,那么你有完全的控制,这使得它更易于pipe理。

  1. 通过使用无锁数据结构来避免locking(例如,使用ConcurrentLinkedQueue而不是同步的ArrayList
  2. 总是以相同的顺序获取锁,例如,为每个锁分配一个唯一的数值,并在获取具有较高数值的锁之前获取数值较低的锁
  3. 超时后释放你的锁(从技术上讲,这不能防止死锁,它只是在发生之后帮助解决它们)

阅读并理解Java:并发与实践。 这不是关于避免死锁的“提示”。 我绝不会聘请一个懂得一些技巧的开发人员来避免死锁,并且经常避免死锁。 这是关于理解并发。 幸运的是,有一个关于这个主题的综合性中级书籍,所以请阅读它。

  1. 不要使用锁。
  2. 如果你必须的话,把你的locking在本地。 全局locking可能非常棘手。
  3. 当你拿着锁,尽量less做。
  4. 使用条纹只能locking数据段
  5. 喜欢不可变的types。 很多时候这意味着复制数据而不是共享数据。
  6. 请使用比较和设置(CAS)机制,例如,请参阅AtomicReference 。

给定一个deviseselect,使用消息传递,只有锁在队列推/popup。 这并不总是可能,但如果是的话,你将会有很less的死锁。 你仍然可以得到他们,但你必须努力:)

在防止死锁方面,几乎只有一个大规则:

如果您需要在代码中使用多个锁,请确保每个人始终以相同的顺序获取它们。

保持你的代码免于locking应该永远是你的目标。 你可以尝试使用不可变或线程本地对象和无锁数据结构来摆脱它们。

这是一个死锁的典型例子:

 public void methodA(){ synchronized(lockA){ //... synchronized(lockB){ //... } } } public void methodB(){ synchronized(lockB){ //... synchronized(lockA){ //... } } } 

如果被许multithreading调用,这个方法可能会创build一个很好的死锁。 这是因为对象被locking的顺序不同 。 这是死锁的最常见的原因之一,所以如果你想避免它们,确保locking顺序

  1. 避免嵌套locking。 这是死锁的最常见的原因。 如果您已经拥有一个锁,请避免locking另一个资源。如果您只使用一个对象锁,则几乎不可能发生死锁。

  2. 只locking需要的东西。 像locking对象的特定字段,而不是locking整个对象,如果它符合您的目的。

  3. 不要无限期地等待。

  1. 除非需要,否则不要通过多个线程共享数据。 如果数据在创build/初始化后无法更改,请保留最终variables。
  2. 如果您无法避免多个线程之间的共享数据,请使用粒度synchronized块或locking 。
  3. 如果您只使用synchronized代码块,请确保按某种顺序获取/释放锁。
  4. 注意其他select:volatile或AtomicXXXvariables或Lock API

相关的SE问题:

避免在Java中同步(this)?

Java中volatile和synchronized的区别

易失性布尔与AtomicBoolean