JAVA死锁的写法

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

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(); }

 

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

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(); } } }

 

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

相关文章
相关标签/搜索