当两个线程同时运行时,A线程拥有lock A,在等待lock B,而B线程拥有lock B,在等待lock A,那么这两个线程都在等待对方释放锁,并且谁也不会先释放锁,那么就陷入了死锁。
死锁的解决办法有三个,设置加锁顺序、设置加锁时限、开启死锁检测。
加锁顺序
当多个线程需要相同的一些锁,但是按照不同的顺序加锁,死锁就很容易发生。如果能确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生。线程只有获得了从顺序上排在前面的锁之后,才能获取后面的锁。
按照顺序加锁是一种有效的死锁预防机制。但是,这种方式需要你事先知道所有可能会用到的锁,并对这些锁做适当的排序,有些时候这是无法预知的。
加锁时限
在尝试获取锁的时候加一个超时时间,也就是在尝试获取锁的过程中如果超过了这个时限该线程则放弃对该锁请求。如果一个线程没有在给定的时限内成功获得所有需要的锁,则会进行回退并释放所有已经获得的锁,然后等待一段随机的时间再重试。这段随机的等待时间让其它线程有机会尝试获取相同的这些锁,并且让该应用在没有获得锁的时候可以继续运行。
不过由于存在线程执行的超时,所以不能认为超时了就一定是出现了死锁。也可能是因为获得了锁的线程(导致其它线程超时)需要很长的时间去完成它的任务。
超时和重试机制是为了避免在同一时间出现的竞争,但是当线程很多时,其中两个或多个线程的超时时间一样或者接近的可能性就会很大,因此就算出现竞争而导致超时后,由于超时时间一