所谓死锁是指两个或两个以上的线程在执行过程中 , 因争夺资源而造成的一种互相等待的现象 , 若无外力作用 , 它们都将无法推进下去 。
以下分别使用 lock 与 synchronized 来产生死锁 , 再定位与分析
一、制造死锁synchronized 版本:
public class DeadLockDemo {public static void main(String[] args) {Object lock1 = new Object();Object lock2 = new Object();new Thread(() -> {synchronized (lock1) {// 线程 t1 持有 lock1锁 , 还要获取 lock2 锁(但 lock2 t2线程占有)System.out.println(Thread.currentThread().getName() + " get lock1 ");try {TimeUnit.MILLISECONDS.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock2) {}}}, "t1").start();new Thread(() -> {synchronized (lock2) {// 线程 t2 持有 lock2锁 , 还要获取 lock1 锁(但 lock1被 t1线程占有)System.out.println(Thread.currentThread().getName() + " get lock2 ");synchronized (lock1) {}}}, "t2").start();}}
Lock版本:
public class DeadLockDemo {public static void main(String[] args) {Lock lock1 = new ReentrantLock();Lock lock2 = new ReentrantLock();// 线程 t1 持有 lock1 , 等到 lock2 锁的到来(但 lock2被 t2线程占用)new Thread(() -> {try {lock1.lock();System.out.println(Thread.currentThread().getName() + " get lock1 ");TimeUnit.MILLISECONDS.sleep(100);// 设置延时lock2.lock();System.out.println(Thread.currentThread().getName() + " get lock2 ");} catch (InterruptedException e) {e.printStackTrace();} finally { lock1.unlock();}}, "t1").start();// 线程 t2 持有 lock2 , 等到 lock1 锁的到来(但 lock1被 t1线程占用)new Thread(() -> {try {lock2.lock();System.out.println(Thread.currentThread().getName() + " get lock1 ");lock1.lock();System.out.println(Thread.currentThread().getName() + " get lock2 ");} finally { lock2.unlock();}}, "t2").start();}}
二、死锁现象
文章插图
程序不停止 , 也不报错 , 一直卡着 。
三、检测方式以下使用Java自带工具进行检测 , 使用三种不同方法检测
1、使用jps、jstack检测
- 打开cmd , 输入jps -l , 找到pid
文章插图
- 接着输入jstack pid , 查看线程堆栈信息
文章插图
- 日志太多 , 直接拖到最后几行 , 可以看到如下信息
文章插图
2、使用jconsole工具检测
- cmd输入jconsole , 会自动打开软件 。选择本地对应的进程 , 点击连接打开软件
文章插图
- 点击检测死锁
文章插图
- 可以看到具体的线程信息
文章插图
3、使用jvisualvm工具检测
- cmd窗口输入jvisualvm 会自动打开软件
文章插图
- 双击对应的进程 , 查看所有线程状态 。可以看到死锁信息
文章插图
- 点击右上角的线程dump , 可以查看具体的堆栈信息
文章插图
四、解决死锁问题产生死锁的必要条件:
- 互斥条件:一个资源每次只能被一个线程使用;
- 请求与保持条件:一个线程因请求资源而阻塞时 , 对已获得的资源保持不放;
- 不剥夺条件:线程已获得的资源 , 在未使用完之前 , 不能强行剥夺;
- 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系;
- 详解Linux死锁概念 死锁的四个必要条件
- 烟雨江湖70级副本怎么进 烟雨江湖70级副本多长战力可以过
- 明日之后辐射高校伦琴值消除方法 明日之后怎么降低伦琴值
- 三国志战略版卧薪尝胆怎么获得 三国志战略版卧薪尝胆战法搭配推荐
- 一梦江湖怎么赚钱 一梦江湖赚铜币攻略
- 剑与远征的荒鸦边界攻略 剑与远征的荒鸦边界怎么过关
- 奥拉星手游杨戬突破怎么打 奥拉星手游杨戬攻略
- 房子走廊尽头是厕所,这样好不好,要怎么才能化解?-阳宅风水
- 云顶手游悄然变味 云顶手游怎么把牌给其他人看
- 如何拥有一个国际品牌的红酒 怎么选择红酒的品牌