前言
若开启多线程,操作同一资源会导致多个线程抢夺执行时间而导致资源出现错误,为解决这一问题我们通常会为线程加锁。但加锁之后也会导致线程进入死锁状态。
一、什么是线程死锁
我们用画家和作家的例子来剖析线程死锁,画家和作家都需要同时拿到纸和笔进行创作,不过在画家和作家面前只有同一个资源包含纸和笔,画家和作家拿着彼此都需要的资源不肯放手,并且互相都想拿到对方的资源这就是线程死锁
二、代码实现
##1.资源类
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;
}
}
2.创建画家和作家
###1.画家类
public class Painter extends Thread{
private Resource resource;
//将测试类创造好的resource对象传递进来,保证作家和画家公用一个resource资源
public void prepare(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
Paper paper = resource.getPaper();//获取resource中的纸
//画家子线程在在拿到纸的同时去获取笔
synchronized (paper) {
//锁住resource中的纸,达到画家同时拿到之和笔的要求
System.out.println("画家拿到了纸");
try {
Thread.sleep(1000*2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Pen pen = resource.getPen();
synchronized (pen) {
System.out.println("画家拿到了笔在创作");
}
}
}
}
###2.作家类
public class Writer extends Thread {
private Resource resource;
//将测试类创造好的resource对象传递进来,保证作家和画家公用一个resource资源
public void prepare(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
Pen pen = resource.getPen();
synchronized (pen) {
System.out.println("作家拿到了笔");
try {
Thread.sleep(1000*9);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Paper paper = resource.getPaper();
synchronized (paper) {
System.out.println("作家拿到了纸在写作");
}
}
}
}
##3.测试类
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建纸和笔的对象
Pen pen = new Pen();
Paper paper = new Paper();
//创建resource
Resource resource = new Resource(pen, paper);
//创建作家对象
Writer writer = new Writer();
writer.prepare(resource);//传递resource保证作家和画家公用一个resource资源
//创建画家对象
Painter painter = new Painter();
painter.prepare(resource);
//开启画家和作家的子线程
writer.start();
painter.start();
}
}
总结
1.线程死锁指的的是画家和作家都需要拿到纸和笔,画家先拿到纸作家先拿到笔,彼此抱着不放,并且想要拿到对方手里的资源
2.解决线程死锁–设置画家在线程开启之后先进行休眠,确保作家线程执行完成,这样就不会导致多个线程操作同一个资源,造成线程死锁