死锁知识点

解释了什么是死锁,包含死锁和解开死锁的例子。

Posted by LJJ on March 8, 2019

死锁

  • 多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形。

下面展示的正是死锁的代码,吃西瓜的方式有两种:1.先拿起西瓜;再拿起西瓜刀。2.先拿起西瓜刀,再拿起西瓜。而下面的过程中,拿起西瓜需要拿起西瓜刀,而拿起西瓜刀又需要拿起西瓜。这样,就形成了死锁。线程停止在小花先拿起西瓜刀,小明先拿起西瓜,两者相互占用,谁都没有办法继续执行下去。

// 定义水果类
class fruits {
	String spcies; //种类
	int fnums; // 数目
	public fruits(String spcies,int fnums) {
		this.spcies = spcies;
		this.fnums = fnums;
	}
}

// 定义切水果工具类
class tools{
	String toolName; // 工具名
	public tools(String toolName) {
		this.toolName = toolName;
	}
}

//定义吃水果方式
class eatStyle extends Thread {
	boolean flag; // 线程判断
	String personName; // 人名
	static fruits f = new fruits("西瓜",5);
	static tools t = new tools("西瓜刀");

​ public eatStyle(boolean flag,String personName) { this.flag = flag; this.personName = personName; }

​ @Override public void run() { eat(); }

    void eat() {
    	if(flag) {
    		synchronized (f) {
				System.out.println(personName+"先拿起:"+f.spcies);
				
				try {
					Thread.sleep(1000);
					synchronized (t) {
						System.out.println(personName+"再拿起:"+t.toolName);
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}    		
    	}else {
			synchronized (t) {
				System.out.println(personName+"先拿起:"+t.toolName);
				
				try {
					Thread.sleep(2000);
					synchronized (f) {
						System.out.println(personName+"再拿起:"+f.spcies);
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}	
		}
	}
}

public class TestLockDead {
	
	public static void main(String[] args) {
		eatStyle p1 = new eatStyle(true,"小明");
		eatStyle p2 = new eatStyle(false,"小花");
		// 启动线程
		p1.start();
		p2.start();
	}
}

控制台输出效果如图,其中右下角红点说明线程锁死,仍然在运行:

死锁.PNG

而死锁代码的解决方案就是下面这段代码,与上面的区别在于第二个同步(synchronized)关键字块没有放到第一个同步(synchronized)关键字块中去,两者是先后执行的关系;

 void eat() {
        	if(flag) {
        		synchronized (f) {
    				System.out.println(personName+"先拿起:"+f.spcies);
    				
    				try {
    					Thread.sleep(1000);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
        		
        		synchronized (t) {
    				System.out.println(personName+"再拿起:"+t.toolName);
    			}
        		
        	}else {
    			synchronized (t) {
    				System.out.println(personName+"先拿起:"+t.toolName);
    				
    				try {
    					Thread.sleep(2000);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    			synchronized (f) {
    				System.out.println(personName+"再拿起:"+f.spcies);
    			}
    		}
    	}

控制台输出结果:

解死锁.PNG