详细解析死锁形成的原因

 首先,了解死锁,先简略了解,代码块的锁: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()唤醒线程一。
                       线程一执行代码。

      机智的你一定懂了。

猜你喜欢

转载自blog.csdn.net/qq_37334150/article/details/80286801
今日推荐