java 死锁例子以及闭锁使用确保死锁产生
今天在参悟他人面经过程中发现一个“简单”的问题:编写一个死锁的代码实例。
看到这个问题,被一个个“高深”的问题虐的怀疑人生的我立马撸了一个java死锁的例子。
1 public class Deadlock { 2 3 //两个被锁的元素 4 private Object l = new Object(); 5 private Object r = new Object(); 6 7 //两种相反的加锁顺序 8 public void lrLock(){ 9 synchronized (l) { 10 System.out.println("lrLock lock l"); 11 try { 12 Thread.sleep(2500);//sleep不释放锁,让当前线程进入TIMED_WAITING状态,尽量使另一个线程把r资源锁住 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 synchronized (r) { 17 System.out.println("lrLock lock r----no dead lock"); 18 } 19 } 20 } 21 22 public void rlLock(){ 23 synchronized (r) { 24 try { 25 Thread.sleep(500); 26 } catch (InterruptedException e) { 27 e.printStackTrace(); 28 } 29 System.out.println("rlLock lock r"); 30 synchronized (l) { 31 System.out.println("rlLock lock l----no dead lock"); 32 } 33 } 34 } 35 }
再来一段main方法调用该实例
1 public static void main(String[] args) { 2 3 Deadlock deadlock = new Deadlock(); 4 Thread threadA = new Thread(new Runnable() { 5 public void run() { 6 deadlock.lrLock(); 7 } 8 }); 9 Thread threadB = new Thread(new Runnable() { 10 public void run() { 11 deadlock.rlLock(); 12 } 13 }); 14 15 threadA.start(); 16 threadB.start(); 17 }
啊哈,这个送分题还不是分分钟被我解决了~吗???等等,运行怎么没产生死锁?
怎么运行是这个玩意儿?我可爱的死锁嘞?我还特意的用sleep方法让第二个线程上锁的机会增加呢,可,莫非是我脸黑?再来一次,还是没出现死锁,再来亿次!还是没有。
陷入沉思的我,这,我菜到连一个死锁都写不出来了嘛,莫非,莫非是虚拟机运行时用了自旋锁优化?对!一定是这样(自旋锁其实针对的是同一个资源的锁,和这个例子并没有太大的联系)。
就在我自以为找到了原因之时,再一次的运行秒打了我的脸,原来之前只是脸不好没运行出死锁的情况而已。
这就很尴尬了呀,难道我打的代码还要看机器的心情而不能按照我的意愿来,想让他死锁就死锁嘛?
一番思考之后,我把代码改成了下面那样。
public class Deadlock { private Object l = new Object(); private Object r = new Object(); //用闭锁保证一个线程锁住l资源,另一个线程锁住r资源 private CountDownLatch latch = new CountDownLatch(2); public void lrLock(){ synchronized (l) { latch.countDown(); System.out.println("lrLock lock l"); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (r) { System.out.println("lrLock lock r----no dead lock"); } } } public void rlLock(){ synchronized (r) { System.out.println("rlLock lock r"); latch.countDown(); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (l) { System.out.println("rlLock lock l----no dead lock"); } } } }
闭锁的使用,保证A线程能锁住l资源并且A线程请求r资源前B线程已经把r资源锁住导致死锁的产生。
啊哈,这下我可以想运行出死锁就运行出来了。
舒服了,收工!