死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
java 死锁产生的四个必要条件:
1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。下面用java代码来模拟一下死锁的产生。
一、多个锁之间的嵌套产生死锁。
class Zhangsan {
public void say() {
System.out.println("你给我画,我就给你书");
}
public void get() {
System.out.println("张三获得了画");
}
}
class Lisi {
public void say() {
System.out.println("你给我书,我就给你画");
}
public void get() {
System.out.println("李四获得了书");
}
}
class ThreadDemo implements Runnable {
// 创建对象
private static Zhangsan zhangsan = new Zhangsan();
private static Lisi lisi = new Lisi();
public boolean tag = true;// 标记(张三李四线程执行不同代码的标记)
@Override
public void run() {
if (tag == true) {// 张三
synchronized (zhangsan) {
zhangsan.say();// 你给我画,我就给你书
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lisi) {
zhangsan.get();// 获得画
}
}
} else {// 李四
/* try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}*/
synchronized (lisi) {
lisi.say();// 你给我书,我就给你画
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (zhangsan) {
lisi.get();// 李四获得了书
}
}
}
}
}
public class DaneLock {
public static void main(String[] args) {
ThreadDemo zhangsanDemo = new ThreadDemo();
zhangsanDemo.tag = true;
ThreadDemo lisiDemo = new ThreadDemo();
lisiDemo.tag = false;
Thread tzhangsan = new Thread(zhangsanDemo, "张三");
Thread tlisi = new Thread(lisiDemo, "李四");
tzhangsan.start();
tlisi.start();
}
}
解决方案如下:避免资源竞争
class Zhangsan {
public void say() {
System.out.println("你给我画,我就给你书");
}
public void get() {
System.out.println("张三获得了画");
}
}
class Lisi {
public void say() {
System.out.println("你给我书,我就给你画");
}
public void get() {
System.out.println("李四获得了书");
}
}
class ThreadDemo implements Runnable {
// 创建对象
private static Zhangsan zhangsan = new Zhangsan();
private static Lisi lisi = new Lisi();
public boolean tag = true;// 标记(张三李四线程执行不同代码的标记)
@Override
public void run() {
if (tag == true) {// 张三
synchronized (zhangsan) {
zhangsan.say();// 你给我画,我就给你书
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (lisi) {
zhangsan.get();// 获得画
}
} else {// 李四
/* try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}*/
synchronized (lisi) {
lisi.say();// 你给我书,我就给你画
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (zhangsan) {
lisi.get();// 李四获得了书
}
}
}
}
public class DaneLock {
public static void main(String[] args) {
ThreadDemo zhangsanDemo = new ThreadDemo();
zhangsanDemo.tag = true;
ThreadDemo lisiDemo = new ThreadDemo();
lisiDemo.tag = false;
Thread tzhangsan = new Thread(zhangsanDemo, "张三");
Thread tlisi = new Thread(lisiDemo, "李四");
tzhangsan.start();
tlisi.start();
}
}
总结:解决死锁就要避免死锁产生的条件