Java 多线程之死锁:
定义:
当一个线程永远地持有一个锁,并且其他线程都尝试去获得这个锁时,那么它们将永远被阻塞,这个我们都知道。如果线程A持有锁L并且想获得锁M,线程B持有锁M并且想获得锁L,那么这两个线程将永远等待下去,这种情况就是最简单的死锁形式。
eg: 下面是一个造成死线程的例子。
package com.newtouch.multiThread;
public class DeadLockDemo {
private static StringA ="A";
private static StringB ="B";
private void deadLock() {
Thread t1 =new Thread(new Runnable() {
@Override
public void run() {
synchronized (A) {
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (B){
System.out.print("1");
}
}
});
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
synchronized (B){
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (A){
System.out.print("2");
}
}
});
t1.start();
t2.start();
}
public static void main(String[] args){
new DeadLockDemo().deadLock();
}
}
线程t1和线程t2,都占有对方拥有的锁,都不能获得锁,这样就形成了死锁。
当然出现死锁的情况很多也很复杂。比如生产者和消费者这种方式情况,以后说到了
notifyAll(),notify(),wait()的时候在举例。
当线程出现了死锁可以通过jps查看当前线程,并用jstak查看堆栈。
具体的大家可以自己百度,这里不做说明。
避免死锁的几个常见方法:
1.避免一个线程同时获取多个锁。
2.避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
3.尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
4.对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。
5.设计时考虑清楚锁的顺序,尽量减少嵌在的加锁交互数量
参考资料:Java并发编程数量。
网友评论