并发编程学习(七):线程活跃性:死锁、活锁、饥饿

       线程活跃性 是指代码有限,但由于某种原因,导致线程一直未执行完成。

1、死锁

       指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

例如:

        t1线程获得了lock1对象锁,接下来想获取lock2对象锁。

        t2线程获得了lock2对象锁 ,接下来想获取lock1对象锁。       

示例代码:

@Slf4j
public class DeadLock {
    private static final Object lock1 = new Object();
    private static final Object lock2 = new Object();

    public static void main(String[] args) {

        new Thread(() -> {
            while (true) {
                synchronized (lock1) {
                    log.debug("t1线程获得lock1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (lock2) {
                        log.debug("t1线程获得lock2");
                    }
                }
            }
        }, "t1").start();

        new Thread(() -> {
            synchronized (lock2) {
                log.debug("t2线程获得lock2");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1) {
                    log.debug("t2线程获得lock1");
                }
            }
        }, "t2").start();
    }
}

 以上代码就会造成死锁,导致t1、t2线程都在等待,无法结束,运行结果如下

1.1、定位死锁

        详细的死锁检测方式:4个java死锁检测工具:jstack、jconsole、jvisualvm、jmc - 知乎,以下先列出两种方式。

1.1.1、方式一:使用jconsole工具 

                JConsole 是一个Java内置性能分析器,使用详见:JConsole详解 

                jconsole 还可以查看堆内存、CPU、线程数 等其他信息。

点击检测死锁,即可以查看存在的死锁线程信息。

t1线程信息:会显示阻塞的锁对象,以及持有该锁的线程。同时会显示死锁的代码位置。

 t2线程信息:会显示阻塞的锁对象,以及持有该锁的线程。同时会显示死锁的代码位置。

1.1.2、方式二:使用jps定位进程id,再用jstack定位死锁

        jps命令:列出所有的java进程。

        jstack:打印指定Java进程、核心文件或远程调试服务器的Java线程的Java堆栈跟踪信息。

                 可以生成JVM当前时刻的线程快照。线程快照是当前JVM内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。

 jstack命令 在最后会打印死锁信息。即可定位到死锁的类和行数。

2、活锁

        多个线程之间,在互相改变对方的执行条件,导致谁都没有办法结束。

3、饥饿

        饥饿:一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执行的状态。

Java中导致饥饿的原因:

  • 高优先级线程吞噬所有的低优先级线程的CPU时间。
  • 线程被永久堵塞在一个等待进入同步块的状态,因为其他线程总是能在它之前持续地对该同步块进行访问。
  • 线程在等待一个本身也处于永久等待完成的对象(比如调用这个对象的wait方法),因为其他线程总是被持续地获得唤醒。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值