Java中的线程死锁
线程死锁概念
两个或两个以上的线程在执行过程中同时被阻塞,它们中的某个或者全部都在等待某个资源被释放,由于线程被无限期的阻塞,系统处于死锁状态或系统产生了死锁,这些永远在互相等待的线程被称为线程死锁。
线程/资源 | 资源1 | 资源2 |
---|---|---|
线程1 | 占有 | 等待 |
线程2 | 等待 | 占有 |
示例代码:
public static void main(String[] args) {
Object wzLock = new Object();
Object cjLock = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (wzLock) {
System.out.println(Thread.currentThread().getName() + "---> 先玩王者");
synchronized (cjLock) {
System.out.println(Thread.currentThread().getName() + "---> 后玩吃鸡");
}
}
}
},"王者爱好者");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (cjLock) {
System.out.println(Thread.currentThread().getName() + "---> 先玩吃鸡");
synchronized (wzLock) {
System.out.println(Thread.currentThread().getName() + "---> 后玩王者");
}
}
}
},"吃鸡爱好者");
t1.start();
t2.start();
}
执行结果:
线程t1先获取并占有资源wzLock,
线程t2先获取并占有资源cjLock,
由于t1无法再获取cjLock,t2也无法再获取wzLock,从而导致线程一直等待,形成死锁。
启用JDK自带的jconsole查看线程情况
WIN + R --> cmd --> jconsole --> enter
如何避免死锁
死锁产生的四个必要条件:
- 互斥使用:当一个资源被另一个线程使用(占有)时,别的线程不能使用。
- 不可抢占:资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
- 请求和保持:当资源请求者在请求其他的资源的同时保持对原有资源的占有。
- 循环等待:在一个等待队列:P1占有P2的资源,P2占有P3的资源…Pn占有P1的资源,这样就形成了一个等待环路。
当上述四个条件全部成立时,就形成死锁,要想解除死锁只需要破坏上述任何一个条件即可。
代码改造:
public static void main(String[] args) {
Object wzLock = new Object();
Object cjLock = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (wzLock) {
System.out.println(Thread.currentThread().getName() + "---> 先玩王者");
synchronized (cjLock) {
System.out.println(Thread.currentThread().getName() + "---> 后玩吃鸡");
}
}
}
},"王者爱好者");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (wzLock) {
System.out.println(Thread.currentThread().getName() + "---> 先玩吃鸡");
synchronized (cjLock) {
System.out.println(Thread.currentThread().getName() + "---> 后玩王者");
}
}
}
},"吃鸡爱好者");
t1.start();
t2.start();
}