怎么用Java代码写一个死锁?
这道面试题是考察面试者对死锁的了解程度,在这个角度来提问也是很有趣。
首先,我们如果要实现死锁的话有四个必要的条件
- 互斥使用(也就是说当我们的资源被一个线程占有时,那别的线程也就不能使用了)
- 不可抢占(请求线程不能强制从占用线程夺取资源,只能由占有线程主动去释放)
- 请求和保持(当请求线程在请求其他资源的时候要保持对原有资源的占有)
- 循环等待(要存在一个循环等待,也就是说A线程要B资源,而B线程要A资源。这就形成了一个等待环路)
那么我们解决死锁由那些方案呢?
- 设置超时时间(如果我们在某个时间段里面没有拿到锁的话,我们就不再死等了,去做别的事情,比如说用JUC包里面Lock接口提供的tryLock方法,而不是像用synchronized那样去一直等待。)
- 降低锁粒度(比如说一个类如果使用一个锁来保护的话,第一个问题是效率低,还有就是死锁风险非常大,只要能够满足我们业务的要求就去尽量减少锁的使用)
- 避免嵌套锁(我们前面演示的例子就是一个嵌套锁,那么在多线程环境使用时,一旦获取锁的顺序反了,就势必会造成死锁)
- 专锁专用(不要很多功能都去用同一把锁,去避免锁冲突,如果很多线程都用同一把锁,就很容易造成死锁)
- 银行家算法(这种思想有一个著名的算法叫做银行家算法,其核心就是分配资源时先看能不能收回来资源(也就是说在分配之前先算一下如果分配出去了会不会造成死锁,要是收不回来造成死锁就不分配锁给这个线程,要是能收回来就分配。)