1.避免活跃度危险
安全性和活跃度通常相互牵制。使用锁来保证线程安全,但是滥用锁可能引起锁顺序死锁;使用线程池和信号量来约束资源的使用,但是却可能使活动形成资源死锁
死锁
当一个线程永远占有一个锁,而其他线程尝试去获得这个锁,那么它们将永远被阻塞。当线程A占有锁L时,想要获得锁M,但是同时,线程B持有锁M,并尝试获得锁L,两个线程将永远等待下去。这种情况是死锁最简单的形式(致命的拥抱,deadly embrace)。发生在多个线程因环路的锁依赖关系而永远等待的情况下。与很多其他的并发危险相同,死锁很少能被立即发现。一个类如果有发生死锁的潜在可能并不意味着死锁每次都将发生,它只发生在该发生的时候。当死锁出现的时候,往往是遇到了最不幸的时候----在高负载之下。
DB系统的避免死锁设计:一个事务(transaction)可能需要获取锁,并可能一直持有这些锁,直到所有事务都提交。DB的处理:当DB监测到一个事务集发生了死锁(通过在表示==正在等待(is-waiting-for)==关系的有向图上搜索循环),它会选择一个牺牲者,使它退出事务。这个牺牲者释放的资源,使得其他事务能够继续进行。应用程序可以重新执行那个被强行退出的事务,现在这个事务可能就能够成功完成了,因为所有跟它竞争资源的事务都已经完成了。
JVM的处理:当一个Java线程集发生死锁时,“游戏”到此结束—这些线程永远不能再使用了。根据线程完成的不同工作,application可能完全停止或特定子系统停止,可能是性能收到影响。恢复application健康的唯一方式就是中止并重启,然后寄希望于不要再发生同样的事情。
避免和诊断死锁