前言
多线程的学习还是很有意思的,简绍一下在多线程中比较有名的死锁产生的原因,这也是面试比较爱问的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();
}
}
代码如下(输出):
艺术家获得纸
文学家获得笔
总结
运行结果如下
在这里面可以看到红圈里面的方块还是红色的,只能说明程序一直在运行,艺术家线程和文学家线程还一直在争夺对方手里的笔或者纸,这就形成了线程的死锁。