代码如下
public class DeadLockSample {
private final static Object lock1=new Object();
private final static String lock2=new String();
public static void main(String[] args) throws IOException {
newThread("Thread A ",lock1,lock2).start();
newThread("Thread B",lock2,lock1).start();
System.in.read();
}
private static Thread newThread(String threadName,Object lockFirst,Object lockSecond){
return new Thread(() -> {
synchronized (lockFirst){
System.err.println(Thread.currentThread().getName()+" holding lockFirst");
try{
Thread.sleep(3000L);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" waiting lockSecond");
synchronized (lockSecond){
System.err.println(Thread.currentThread().getName()+" holding lockSecond");
}
}
},threadName);
}
}
死锁产生的原因:
两个及两个以上的线程,抢占2把及以上的锁,抢占锁的顺序不一致
避免和处理死锁问题:
1,不使用锁,不使用两把及以上的锁
2,必须使用2把及以上的锁的时候,确保在整个应用程序中对获取锁的顺序是一致的
3,尝试获取具有超时释放的锁,例如Lock中的tryLock来获取锁
4,当发生了java-level的锁时,重启程序来干掉进程/线程
*jps
列举正在运行的虚拟机进程并显示虚拟机执行的主类以及这些进程的唯一ID(PID)
* jstack
用于jvm当前时刻的线程快照,得到jvm当前每一条线程正在执行的堆栈信息,定位线程长时间卡顿问题,如死锁、死循环等问题
福利赠送:
创建线程四种方式
一、继承Thread类
二、实现Runnable接口
三、实现Callable接口
四、使用线程池创建--ExecutorService executorService = Exceutors.newFixedThreadPool( 5 );
(1)使用Executors类中的newFixedThreadPool(int num)方法创建一个线程数量为num的线程池
(2)调用线程池中的execute()方法执行由实现Runnable接口创建的线程;调用submit()方法执行由实现Callable接口创建的线程
(3)调用线程池中的shutdown()方法关闭线程池
数据库死锁
数据库死锁
1,选择一个数据库
2,开启两个会话,每个会话调用‘start transaction;’
3,第一个会话更新id=1的行数据
4,第二个会话更新id=2的行数据
5,第一个会话更新id=2的行数据,此时等待id=2的行的锁
6,第二个会话更新id=1的行数据,此时数据库检测死锁,终止触发死锁的事务,
第一个会话的的等待状态变成正常状态
7,调用‘commit’提交第一个会话事务,数据成功