首先,了解死锁,先简略了解,代码块的锁:synchronized (对象){} 锁住参数对象。 synchronized对象和内容访问单一;
简略扫过一下,死锁和非死锁代码:
死锁:
class Zhangsan{ // 定义张三类 public void say(){ System.out.println("张三对李四说:“你给我画,我就把书给你。”") ; } public void get(){ System.out.println("张三得到画了。") ; } } class Lisi{ // 定义李四类 public void say(){ System.out.println("李四对张三说:“你给我书,我就把画给你”") ; } public void get(){ System.out.println("李四得到书了。") ; } } public class ThreadDeadLock implements Runnable{ private static Zhangsan zs = new Zhangsan() ; // 实例化static型对象 private static Lisi ls = new Lisi() ; // 实例化static型对象 private boolean flag = false ; // 声明标志位,判断那个先说话 public void run(){ // 覆写run()方法 if(flag){ synchronized(zs){ // 同步张三 zs.say() ; System.out.println("张三正在等待李四的画..."); try{ Thread.sleep(500) ; }catch(InterruptedException e){ e.printStackTrace() ; } synchronized(ls){ zs.get() ; } } }else{ synchronized(ls){ ls.say() ; System.out.println("李四正在等待张三的书..."); try{ Thread.sleep(500) ; }catch(InterruptedException e){ e.printStackTrace() ; } synchronized(zs){ ls.get() ; } } } } public static void main(String args[]){ ThreadDeadLock t1 = new ThreadDeadLock() ; // 控制张三 ThreadDeadLock t2 = new ThreadDeadLock() ; // 控制李四 t1.flag = true ; t2.flag = false ; Thread thA = new Thread(t1) ; Thread thB = new Thread(t2) ; thA.start() ; thB.start() ; } }
非死锁:
class Zhangsan1{ // 定义张三类 public void say(){ System.out.println("张三对李四说:“你给我画,我就把书给你。”") ; } public void get(){ System.out.println("张三得到画了。") ; } } class Lisi1{ // 定义李四类 public void say(){ System.out.println("李四对张三说:“你给我书,我就把画给你”") ; } public void get(){ System.out.println("李四得到书了。") ; } } public class ThreadDeadUnLock implements Runnable{ private static Zhangsan1 zs = new Zhangsan1() ; // 实例化static型对象 private static Lisi1 ls = new Lisi1() ; // 实例化static型对象 private boolean flag = false ; // 声明标志位,判断那个先说话 public void run(){ // 覆写run()方法 if(flag){ synchronized(zs){ // 同步张三 zs.say() ; System.out.println("张三正在等待李四的画..."); try{ Thread.sleep(500); zs.wait(); //廖兴广:线程睡眠释放资源 }catch(InterruptedException e){ e.printStackTrace() ; } synchronized(ls){ zs.get() ; } } }else{ synchronized(ls){ ls.say() ; System.out.println("李四正在等待张三的书..."); try{ Thread.sleep(500) ; }catch(InterruptedException e){ e.printStackTrace() ; } synchronized(zs){ ls.get() ; zs.notify(); } } } } public static void main(String args[]){ ThreadDeadUnLock t1 = new ThreadDeadUnLock() ; // 控制张三 ThreadDeadUnLock t2 = new ThreadDeadUnLock() ; // 控制李四 t1.flag = true ; t2.flag = false ; Thread thA = new Thread(t1) ; Thread thB = new Thread(t2) ; thA.start() ; thB.start() ; } }
看完了吗?我相信机智的你一定已经发现了他们那些细小的区别。那么我们来分析一下他们运行的过程,在此要记住一个核心知识:睡眠(sleep)不释放线程资源,wait释放线程资源。
死锁: 创建俩个线程: 线程一synchronized(zs),执行,后面进入睡眠。
在此期间同步锁依旧存在。
线程二synchronized(ls),执行,睡眠
线程一醒来,执行内部锁synchronized(ls),ls对象被占用,等待。。。
线程二醒来,执行内部锁synchronized(zs),zs对象被占用,等待。。。
活锁: 创建俩个线程: 线程一synchronized(zs),执行,后面进入睡眠。wait()释放资源
在此期间synchronized(zs)被解锁.
线程二synchronized(ls),执行,睡眠
线程一未被唤醒
线程二醒来,执行内部锁synchronized(zs),zs对象未被占用,执行代码,notify()唤醒线程一。
线程一执行代码。
机智的你一定懂了。