线程死锁(文学家与艺术家例子)

文章目录

前言

多线程的学习还是很有意思的,简绍一下在多线程中比较有名的死锁产生的原因,这也是面试比较爱问的Java基础之一,所以比较重要,特地挑出来简绍一下下

一、死锁产生的原因

在多线程中使用锁会造成整个程序的效率降低,但是如果出现同步嵌套,就容易产生死锁问题。而死锁就是两个或者两个以上的线程在执行的过程中,因为争夺资源产生的一种互相等待的现象。
如果两个或者多个共享对象,分别持有对方所需的共享的锁,在试图获取对方线程所持有本线程的锁的时候,就容易出现死锁。

二、死锁示例

做一个比较有意思的例子
艺术家和文学家都需要最基本的吃饭家伙纸和笔,但是艺术家先拿到纸,作家先拿到笔,此时,两者都不愿意率先放弃手中的资源,还希望拿到对方的资源,这就会出现线程的死锁

三、死锁代码演示

代码如下(笔类):

public class Pen {

}

代码如下(纸类):

public class Paper {

}

代码如下(资源类):

public class Resource {
	private Pen pen;
	private Paper paper;
	public Resource() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Resource(Pen pen, Paper paper) {
		super();
		this.pen = pen;
		this.paper = paper;
	}
	public Pen getPen() {
		return pen;
	}
	public void setPen(Pen pen) {
		this.pen = pen;
	}
	public Paper getPaper() {
		return paper;
	}
	public void setPaper(Paper paper) {
		this.paper = paper;
	}
}

代码如下(艺术家线程):

public class Artist extends Thread { // 继承
	private Resource resource; // 创建对象

	public void prepace(Resource resource) {
		this.resource = resource;
	}

	@Override
	public void run() { // 重写run()函数
		Paper paper = resource.getPaper();
		synchronized (paper) {// 建立锁
			System.out.println("艺术家获得纸");
			Pen pen = resource.getPen();
			synchronized (pen) { // 建立锁
				System.out.println("艺术家获得笔");
			}
		}
	}
}

代码如下(文学家线程):

public class Litterateur extends Thread { // 继承
	private Resource resource; // 创建对象

	public void prepace(Resource resource) {
		this.resource = resource;
	}

	@Override
	public void run() { // 重写run()函数
		Pen pen = resource.getPen();
		synchronized (pen) { // 建立锁
			System.out.println("文学家获得笔");
			try {
				Thread.sleep(1000 * 1); // 休眠1秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Paper paper = resource.getPaper();

			synchronized (paper) {// 建立锁
				System.out.println("文学家获得纸");
			}
		}
	}
}

代码如下(测试):

public class Test01 {

	public static void main(String[] args) {
		// 创建纸、笔、资源
		Pen pen = new Pen();
		Paper paper = new Paper();
		Resource resource = new Resource(pen, paper);
		// 创建文学家
		Litterateur litterateur = new Litterateur();
		litterateur.prepace(resource);
		// 创建艺术家
		Artist artist = new Artist();
		artist.prepace(resource);
		// 启动文学家线程
		litterateur.start();
		// 启动艺术家线程
		artist.start();
	}

}

代码如下(输出):

艺术家获得纸
文学家获得笔

总结

运行结果如下
线程死锁(文学家与艺术家例子)
在这里面可以看到红圈里面的方块还是红色的,只能说明程序一直在运行,艺术家线程和文学家线程还一直在争夺对方手里的笔或者纸,这就形成了线程的死锁。

上一篇:一文了解AAAI国际会议–附: 各年论文连接


下一篇:深度之眼paper会员计算机视觉代码复现资料