并发编程中为什会出现死锁呢?
我们还是来看个案例
并发编程死锁的案例
public class DeadLockDemo {
private static String A="A";
private static String B="B";
public static void main(String[] args) {
new DeadLockDemo().deadLock();
}
private void deadLock() {
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (A) {
try {
Thread.currentThread().sleep(2000);
} catch (Exception e) {
// TODO: handle exception
}
synchronized (B) {
System.out.println("1");
}
}
}
});
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (B) {
synchronized (A) {
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("2");
}
}
}
});
t1.start();
t2.start();
}
}
分析
在上述案例中,由于线程机制是抢占式的,通俗的话说就是,程序执行的先后是不确定的。
因此可能会出现这种情况:
- 线程一的情况:
线程一先用synchronized关键字锁住了A变量禁止其他线程使用,之后当尝试锁住B资源,但是发现线程二已经锁住了B变量,线程一不得不继续等待线程二释放锁住的B
- 线程二的情况
线程二先锁住了B变量禁止其他线程使用,然后尝试锁住A资源,由于此时线程一已经锁住了变量A,因此线程二不得不等待线程一释放锁住的A后才能使用
线程一在等待线程二释放锁,线程二在等待线程一释放锁,如此循环,这就造成了死锁
总结
当线程中获取的锁太多,可能会出现死锁
避免死锁的几个常见方法
- 避免一个线程同时获取多个锁
- 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
- 尝试使用定时锁,使用lock.tryLock(timeout) 来替代使用内部锁机制
- 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。
本文标题:9. Java 并发编程的魅力之死锁
本文链接:https://blog.quwenai.cn/post/3123.html
版权声明:本文不使用任何协议授权,您可以任何形式自由转载或使用。






还没有评论,来说两句吧...