多线程下还是要考虑一下死锁的发生情况,避免遇到这种问题时被动无措,死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者彼此通信而造成的一种阻塞的现象,若无外力作用,他们都将无法推进下去。此时称系统处于死锁状态或者系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
理解死锁的基础概念后,我这边提供一个编写一个死锁的示例程序作为演示和排查的解决方法供于思考。
代码语言:javascript复制package com.wpw.threadconcurrent;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
@Slf4j
public class SynchronizedThread implements Runnable {
private static Object objectA = new Object();
private static Object objectB = new Object();
private boolean flag;
public SynchronizedThread(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
if (flag) {
synchronized (objectA) {
System.out.println("当前线程的名称:" Thread.currentThread().getName() "锁住了对象A" objectA);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
log.error("异常信息:{}", e);
}
synchronized (objectB) {
System.out.println("当前线程的名字:" Thread.currentThread().getName() "锁住了对象B" objectB);
}
}
} else {
synchronized (objectB) {
System.out.println("当前线程的名字:" Thread.currentThread().getName() "锁住了对象B" objectB);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
log.error("异常信息:{}", e);
}
synchronized (objectA) {
System.out.println("当前线程的名字:" Thread.currentThread().getName() "锁住了对象A" objectA);
}
}
}
}
private void sleep() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
}
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(new SynchronizedThread(true), "线程A");
Thread threadB = new Thread(new SynchronizedThread(false), "线程B");
threadA.start();
threadB.start();
}
}
看下控制台输出的日志
代码语言:javascript复制当前线程的名称:线程A锁住了对象Ajava.lang.Object@7defb506
当前线程的名字:线程B锁住了对象Bjava.lang.Object@108ea51d
我们看下线程A拿到了资源对象objectA,线程B拿到了资源对象B,但是两者之间存在一定的时间间隔,彼此都没有释放所持有的资源,导致彼此互相等待,造成了死锁现象。
如何排查已经产生了死锁呢,我们通过cmd命令进入控制台,通过jps看下当前程序的pid。
先找到pid,linux环境下可以根据ps -aux | grep "服务名称"找到pid,找到pid之后我们可以通过 jstack-l pid来看下对应线程信息。
我们看到打印的信息发现已经存在一个死锁,那么如何解决这个问题呢,找到对应的代码进行逻辑的排查即可,避免资源的互相竞争。
这次要分享的内容到这里就结束了,喜欢文章的欢迎转发和分享。