面试题:用java实现一个死锁
点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
实现一个最简单的死锁(Java版)
/**
* @author wall
* @date 2019/7/29 16:42
* @description 实现一个死锁:A线程获取B线程占有的锁,B线程获取A线程占有的锁
*/
public class DeadLock {
//定义两把锁
private static ReentrantLock lockA = new ReentrantLock();
private static ReentrantLock lockB = new ReentrantLock();
//测试
public static void main(String[] args) {
//启动线程A,B
new Thread(new A()).start();
new Thread(new B()).start();
}
static class A implements Runnable{
@Override
public void run() {
Thread.currentThread().setName("A线程");
//获取锁A
lockA.lock();
System.out.println(Thread.currentThread().getName()+"获取锁A");
//模拟业务操作
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//再获取锁B
lockB.lock();
System.out.println(Thread.currentThread().getName()+"获取锁B");
lockA.unlock();
lockB.unlock();
}
}
static class B implements Runnable{
@Override
public void run() {
Thread.currentThread().setName("B线程");
//获取锁B
lockB.lock();
System.out.println(Thread.currentThread().getName()+"获取锁B");
//模拟业务操作
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//再获取锁A
lockA.lock();
System.out.println(Thread.currentThread().getName()+"获取锁A");
}
}
}
产生死锁的四大必要条件
避免死锁的方式
银行家算法
避免多次锁定。尽量避免同一个线程对多个 Lock 进行锁定。例如上面的死锁程序,主线程要对 A、B 两个对象的 Lock 进行锁定,副线程也要对 A、B 两个对象的 Lock 进行锁定,这就埋下了导致死锁的隐患。
具有相同的加锁顺序。(给锁添加顺序)如果多个线程需要对多个 Lock 进行锁定,则应该保证它们以相同的顺序请求加锁。比如上面的死锁程序,主线程先对 A 对象的 Lock 加锁,再对 B 对象的 Lock 加锁;而副线程则先对 B 对象的 Lock 加锁,再对 A 对象的 Lock 加锁。这种加锁顺序很容易形成嵌套锁定,进而导致死锁。如果让主线程、副线程按照相同的顺序加锁,就可以避免这个问题。
使用定时锁。程序在调用 acquire() 方法加锁时可指定 timeout 参数,该参数指定超过 timeout 秒后会自动释放对 Lock 的锁定,这样就可以解开死锁了。
死锁检测。死锁检测是一种依靠算法机制来实现的死锁预防机制,它主要是针对那些不可能实现按序加锁,也不能使用定时锁的场景的。
死锁的解除
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:
https://blog.csdn.net/weixin_42228338/article/details/97686461
评论