博为峰Java技术题 ——JavaSE 避免死锁Ⅱ

[加锁时限]java

博为峰小博老师工具

另一个能够避免死锁的方法是在尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程当中若超过了这个时限该线程则放弃对该锁请求。若一个线程没有在给定的时限内成功得到全部须要的锁,则会进行回退并释放全部已经得到的锁,而后等待一段随机的时间再重试。这段随机的等待时间让其它线程有机会尝试获取相同的这些锁,而且让该应用在没有得到锁的时候能够继续运行(加锁超时后能够先继续运行干点其它事情,再回头来重复以前加锁的逻辑)。线程

如下是一个例子,展现了两个线程以不一样的顺序尝试获取相同的两个锁,在发生超时后回退并重试的场景:code

5.1tmp_副本.png

在上面的例子中,线程2比线程1早200毫秒进行重试加锁,所以它能够先成功地获取到两个锁。这时,线程1尝试获取锁A而且处于等待状态。当线程2结束时,线程1也能够顺利的得到这两个锁(除非线程2或者其它线程在线程1成功得到两个锁以前又得到其中的一些锁)。blog

须要注意的是,因为存在锁的超时,因此咱们不能认为这种场景就必定是出现了死锁。也多是由于得到了锁的线程(致使其它线程超时)须要很长的时间去完成它的任务。资源

此外,若是有很是多的线程同一时间去竞争同一批资源,就算有超时和回退机制,仍是可能会致使这些线程重复地尝试但却始终得不到锁。若是只有两个线程,而且重试的超时时间设定为0到500毫秒之间,这种现象可能不会发生,可是若是是10个或20个线程状况就不一样了。由于这些线程等待相等的重试时间的几率就高的多(或者很是接近以致于会出现问题)。 (超时和重试机制是为了不在同一时间出现的竞争,可是当线程不少时,其中两个或多个线程的超时时间同样或者接近的可能性就会很大,所以就算出现竞争而致使超时后,因为超时时间同样,它们又会同时开始重试,致使新一轮的竞争,带来了新的问题。)get

这种机制存在一个问题,在Java中不能对synchronized同步块设置超时时间。你须要建立一个自定义锁,或使用Java5中java.util.concurrent包下的工具。写一个自定义锁类不复杂,但超出了本文的内容。同步

相关文章
相关标签/搜索