上机实战:写个多线程死锁的例子
上代码:
public class DeadLockDemoOnline {
private static String locka = "locka";
private static String lockb = "lockb";
public void methodA(){
synchronized (locka){
System.out.println("我是A方法中获得了锁A "+Thread.currentThread().getName() );
//让出CPU执行权,不释放锁
try {
//Thread.sleep(2000);
System.out.println("methodA");
} catch (Exception e) {
e.printStackTrace();
}
synchronized(lockb){
System.out.println("我是A方法中获得了锁B "+Thread.currentThread().getName() );
}
}
}
public void methodB(){
synchronized (lockb){
System.out.println("我是B方法中获得了锁B "+Thread.currentThread().getName() );
//让出CPU执行权,不释放锁
try {
//Thread.sleep(2000);
System.out.println("methodB");
} catch (Exception e) {
e.printStackTrace();
}
synchronized(locka){
System.out.println("我是B方法中获得了锁A "+Thread.currentThread().getName() );
}
}
}
public static void main(String [] args){
System.out.println("主线程运行开始运行:"+Thread.currentThread().getName());
DeadLockDemoOnline deadLockDemo = new DeadLockDemoOnline();
for(int i=0;i<3;i++){
new Thread(()->{
deadLockDemo.methodA();
}).start();
new Thread(()->{
deadLockDemo.methodB();
}).start();
}
System.out.println("主线程运行结束:"+Thread.currentThread().getName());
}
}
死锁原因:
线程在获得了锁A并且没有释放的情况下去申请锁B,
这时另一个线程已经获得了锁B,在释放锁B之前又要先获得锁A
因此闭环发生,陷入死锁循环
死锁的4个必要条件
互斥条件:资源不能共享,只能由一个线程使用
请求与保持条件:线程已经获得一些资源,但因请求其他资源发生阻塞,对已经获得的资源保持不释放
不可抢占:有些资源是不可强占的,当某个线程获得这个资源后,系统不能强行回收,只能由线程使用完自己释放
循环等待条件:多个线程形成环形链,每个都占用对方申请的下个资源
只要发生死锁,上面的条件都成立;只要一个不满足,就不会发生死锁
解决方式:
public class FixDeadLockDemo {
private static String locka = "locka";
private static String lockb = "lockb";
public void methodA(){
synchronized (locka){
System.out.println("我是A方法中获得了锁A "+Thread.currentThread().getName() );
//让出CPU执行权,不释放锁
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized(lockb){
System.out.println("我是A方法中获得了锁B "+Thread.currentThread().getName() );
}
}
public void methodB(){
synchronized (lockb){
System.out.println("我是B方法中获得了锁B "+Thread.currentThread().getName() );
//让出CPU执行权,不释放锁
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized(locka){
System.out.println("我是B方法中获得了锁A "+Thread.currentThread().getName() );
}
}
public static void main(String [] args){
System.out.println("主线程运行开始运行:"+Thread.currentThread().getName());
FixDeadLockDemo deadLockDemo = new FixDeadLockDemo();
for(int i=0; i<5;i++){
new Thread(()->{
deadLockDemo.methodA();
}).start();
new Thread(()->{
deadLockDemo.methodB();
}).start();
}
System.out.println("主线程运行结束:"+Thread.currentThread().getName());
}
}
把synchronized送里面拿出来,调整下范围,不要循环去调用
查看死锁的方式你知道哪几个?
方式一:
jps 查看相应的id号 ,jstack id号,日志里有java.lang.Thread.State:BLOCKED(on object monitor)即是死锁
方式二:
jconsole回车,连接相应可能出问题的类文件
双击本地进程中的 PID是当前运行的
进入线程页面后,点击下方 检测死锁
死锁的状态