1.死锁概念
多个线程由于相互抢夺资源进入僵持状态,无法继续推进执行的状态;
举例:a线程拿着锁a,在等待获取锁b;b线程拿着锁b在等待获取锁a;
两个线程僵持,无法继续执行,即为死锁;
2.死锁代码实现
public static void main(String[] args) {
Object a=new Object();//a b对象 当两把锁
Object b=new Object();
//a线程
Thread ta=new Thread(()->{
synchronized (a){//a线程去拿 锁a
System.out.println(Thread.currentThread().getName()+"\t"+"a线程拿到了锁a,接下来要去拿锁b");
try {
Thread.sleep(1000L);//拿完自己的锁 等一会
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b){//a线程去拿 锁b
System.out.println("a线程拿到了锁b?");
}
}
},"线程a");
//b线程
Thread tb=new Thread(()->{
synchronized (b){//b线程去拿 锁b
System.out.println(Thread.currentThread().getName()+"\t"+"b线程拿到了锁b,正要去拿锁a");
try {
Thread.sleep(1000L);//拿完自己的锁 等一会
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (a){//b线程去拿 锁a
System.out.println("b拿到了锁a?");
}
}
},"线程b");
//启动两线程;
ta.start();
tb.start();
}
控制台结果:
a b线程都只拿到了一把锁,在等待获取对方的锁,死锁发生;
3.死锁检查
1.)Jstack
2.)Jcondole
3.1 Jstack
1)在jdk的bin目录下 执行 jps获取当前java进程
15820为我们执行的程序;
2)用jstack 查看堆栈情况;
jstack 15820
3.2 Jconsole
1)执行jconsole,连接到对应java进程;
2)选择线程-线程a/b
a:
b:
4.死锁预防
4.1 按一定顺序获取锁
让a/b两线程都先获取锁a,再去获取锁b;就可以防止死锁发生;
4.2 超时放弃
当僵持后,一定时间获取不到锁,则放弃锁,结束当前线程;