死锁
- 多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形。
下面展示的正是死锁的代码,吃西瓜的方式有两种: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();
}
}
控制台输出效果如图,其中右下角红点说明线程锁死,仍然在运行:
而死锁代码的解决方案就是下面这段代码,与上面的区别在于第二个同步(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);
}
}
}
控制台输出结果: