打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
JAVA死锁的写法(实际工作中要避免)

在java开发中,避免不了要加锁控制程序逻辑,但加锁有可能导致死锁,造成线程永远卡死在等待释放锁,后面的代码得不到执行;
在java里,一般是通过synchronized关键字加锁,在jdk1.5版本中新增了Lock接口显示的加锁,本文讨论用这两种方式实现死锁;
方式一:

public static void main(String[] args) {        Object lock1 = new Object();        Object lock2 = new Object();        ExecutorService service = Executors.newCachedThreadPool();        service.execute(() ->{            while (true){                synchronized (lock2){                    synchronized (lock1){                        System.out.println("Thread1");                    }                }            }        });        service.execute(() ->{            while (true){                synchronized (lock1){                    synchronized (lock2){                        System.out.println("Thread2");                    }                }            }        });        service.shutdown();    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

上面的代码开启了两个线程,两个线程都循环打印字符串,正常来说两个线程都会不断打印,但这里出现了死锁,导致两个线程都会打印停止,逻辑分析:两个线程执行到某一时刻,线程一执行到synchronized (lock2){这一句,获得了对象lock2上的锁,线程二执行到synchronized (lock1){这一句,获得了对象lock1上的锁,接下来,线程一需要执行synchronized (lock1){这一句尝试获取lock1的锁,由于lock1的锁被线程二占用,线程一等待线程二释放lock1的锁,这时线程二需要执行synchronized (lock2){这一句,尝试获取lock2上的锁,由于lock2上的锁被线程一占用,线程二等待线程一释放lock2上的锁,这样,两个线程互相等待释放锁,导致两个线程永远无法执行后面的代码,导致死锁;
方式二:

static final Lock LOCK1 = new ReentrantLock();    static final Lock LOCK2 = new ReentrantLock();    public static void main(String[] args) {        ExecutorService service = Executors.newCachedThreadPool();        service.execute(new PrintTask1(1));        service.execute(new PrintTask2(2));    }    static class PrintTask1 implements Runnable{        private int id = -1;        public PrintTask1(int i){            id = i;        }        @Override        public void run() {            while (true){                LOCK1.lock();                LOCK2.lock();                System.out.println("" + id);                LOCK2.unlock();                LOCK1.unlock();            }        }    }    static class PrintTask2 implements Runnable{        private int id = -1;        public PrintTask2(int i){            id = i;        }        @Override        public void run() {            while (true){                LOCK2.lock();                LOCK1.lock();                System.out.println("" + id);                LOCK2.unlock();                LOCK1.unlock();            }        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

方式二的代码属于显示加锁,使用了jdk1.5新增的Lock接口,与方式一类似,当两个线程执行到某一时刻,线程一执行了LOCK1.lock()获得了LOCK1锁,线程二执行了LOCK2.lock()获得了LOCK2锁,接下来两个线程又要互相等待对方释放锁,导致死锁。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Java中的21种锁,图文并茂的详细解释
JDK的锁Synchronized、ReentrantLock与读写锁
一篇好文,带你深入了解Lock锁 !
java并发(十)死锁 & 活锁
Java并发编程:Lock
高并发Java(5):JDK并发包1(上)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服