先上完整的代码
后续再依次修改代码块得到相应的结论
1 //尝试写一个死锁 感受一下 2 public class DeadLock { 3 public static void main(String[] args) { 4 Object o1 = new Object(); 5 Object o2 = new Object(); 6 //创建两个object对象 7 //创建两个Thread线程 8 Thread T1 = new Thread(new process1(o1,o2)); //两个线程T1、T2共享了相同的两个对象o1、o2 9 Thread T2 = new Thread(new process2(o1,o2)); 10 T1.setName("t1"); 11 T2.setName("t2") ; 12 //star run一下 13 T1.start() ; //----t2 running 14 //-----t1 running 15 T2.start() ; 16 17 18 } 19 } 20 //首先是写一个线程类。 21 class process1 implements Runnable{ 22 Object o1,o2; 23 process1(Object o1,Object o2 ){ 24 this.o1 = o1 ; 25 this.o2 = o2 ; 26 } 27 public void run(){ 28 //先锁o1 再锁o2 29 synchronized(o1){ 30 try{ 31 Thread.sleep(1000); //锁住O1 并睡1s 32 }catch(Exception e ){ 33 e.printStackTrace(); 34 } 35 synchronized(o2){ if(Thread.currentThread().getName().equals("t1")){ //T1成功执行后,输出t1并归还o1 o2两把锁 36 System.out.println("-----t1 running");} 37 if(Thread.currentThread().getName().equals("t2")){ 38 System.out.println("----t2 running");} 39 } 40 } 41 } 42 } 43 44 class process2 implements Runnable{ 45 Object o1,o2; 46 process2(Object o1,Object o2 ){ 47 this.o1 = o1 ; 48 this.o2 = o2 ; 49 } 50 public void run(){ 51 //先锁o2再锁o2 52 synchronized (o2){ //锁住O2并睡1s 53 try{ 54 Thread.sleep(1000); 55 } 56 catch(Exception e ){ 57 e.printStackTrace() ; 58 } 59 synchronized(o1){ 60 if(Thread.currentThread().getName().equals("t1")){ 61 System.out.println("-----t1 running");} 62 if(Thread.currentThread().getName().equals("t2")){ ////T2成功执行后,输出t2并归还o1 o2两把锁 63 System.out.println("----t2 running");} 64 } 65 } 66 } 67 }
实验的关键点在于运用Thread.sleep();对线程的休眠,实现对o1 o2不同的上锁和解锁情况。
代码块A(T1中的run方法):
public void run(){ 28 //先锁o1 再锁o2 29 synchronized(o1){ 30 try{ 31 Thread.sleep(1000); //锁住O1 并睡1s 32 }catch(Exception e ){ 33 e.printStackTrace(); 34 } 35 synchronized(o2){ if(Thread.currentThread().getName().equals("t1")){ //T1成功执行后,输出t1并归还o1 o2两把锁 36 System.out.println("-----t1 running");} 37 if(Thread.currentThread().getName().equals("t2")){ 38 System.out.println("----t2 running");} 39 } 40 } 41 }
代码块B(T2中的run方法):
public void run(){ 51 //先锁o2再锁o2 52 synchronized (o2){ //锁住O2并睡1s 53 try{ 54 Thread.sleep(1000); 55 } 56 catch(Exception e ){ 57 e.printStackTrace() ; 58 } 59 synchronized(o1){ 60 if(Thread.currentThread().getName().equals("t1")){ 61 System.out.println("-----t1 running");} 62 if(Thread.currentThread().getName().equals("t2")){ ////T2成功执行后,输出t2并归还o1 o2两把锁 63 System.out.println("----t2 running");} 64 }
实验1:将块A和B中的Thread.sleep(1000);语句都注释掉
输出结果:大定概率下
-----t1 running
----t2 running
小概率下输出
-----t2 running
----t1 running 出现这样的结果是因为T1更容易获得了较多的CPU时间块,将所有语句执行完毕,并解锁o1 o2,之后才执行T2.star()语句,输出t2 running
实验2:将块A中的Thread.sleep(1000);注释掉
输出结果:很大的几率会输出
-----t1 running
--------中间间隔1s后:
----t2 running
,原因在于语句先执行T1.star()
线程T1中的run语句执行完毕时,线程T2才开始获得CPU时间片,此时的o1 o2已经解锁。T2的run语句块可以顺利执行(包括sleep语句)
很小的几率会出现死锁:此时T2率先获得CPU时间片,并且锁住o2,线程停止1s,这段时间已经足够T1的run语句将o1锁住,于是o1 o2的锁都无法归还 ,形成了死锁
实验3:将块A和块B中的Thread.sleep(1000)都注释掉
输出结果:
必定没有输出,原因在于无论T1还是T2先拿到CPU时间片,都会拿掉一个锁,并且线程阻塞1s,这段时间已经足够另一个线程去拿另外一个锁,于是o1 o2的锁都无法归还,T1 T2中的run语句均无法继续往下执行,程序被锁死。
原文地址:https://www.cnblogs.com/Insertt/p/12117014.html