Java并发编程 - 一个简单的死锁示例和死锁的检查

Posted Helios_Fz的学习笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java并发编程 - 一个简单的死锁示例和死锁的检查相关的知识,希望对你有一定的参考价值。

  一个简单的死锁示例和死锁的检查

Java线程死锁是一个经典的多线程问题。因为不同的线程都在等待根本不可能被释放的锁,从而导致所有的任务都无法继续完成。

1.死锁程序示例

创建类 DeadLockThread:

public class DeadLockThread implements Runnable {

    private Object lock1 = new Object();
    private Object lock2 = new Object();

    private String s;

    public void setS(String s) {
        this.s = s;
    }

    @Override
    public void run() {
        if ("a".equalsIgnoreCase(s)) {
            synchronized (lock1) {
                System.out.println(Thread.currentThread() + " a 正在执行");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock2) {
                    System.out.println("lock1 -> lock2 死锁未生效");
                }
            }
        }
        if ("b".equalsIgnoreCase(s)) {
            synchronized (lock2) {
                System.out.println(Thread.currentThread() + " b 正在执行");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1) {
                    System.out.println("lock2 -> lock1 死锁未生效");
                }
            }
        }
    }
}

创建运行类 Main:

public class Main {

    public static void main(String[] args) throws InterruptedException {
        DeadLockThread deadLockThread = new DeadLockThread();

        deadLockThread.setS("a");
        Thread threadA = new Thread(deadLockThread);
        threadA.start();
        Thread.sleep(200);

        deadLockThread.setS("b");
        Thread threadB = new Thread(deadLockThread);
        threadB.start();
        Thread.sleep(200);
    }
}

运行结果如下:

 2.使用JDK自带工具做死锁后的检查

1.进入JDK安装文件夹中的bin目录,执行jps命令:

 得到正在运行着的线程Main的id值是12295。

2.在执行 jstack -l 12295 命令,查看结果:

由此结果可知,程序有死锁的现象。

3.使用IDEA的FindBugs插件检查可能出现的死锁

右键测试代码所在的包,选择分析包内文件

 分析结果如下:

This method calls Thread.sleep() with a lock held. 
This may result in very poor performance and scalability, or a deadlock, since other threads may be waiting to acquire the lock. 
It is a much better idea to call wait() on the lock, which releases the lock and allows other threads to run.
此方法调用thread.sleep(),并保留一个锁。
这可能会导致性能和可伸缩性非常差,或者出现死锁,因为其他线程可能正在等待获取锁。
最好对锁调用wait(),这样可以释放锁并允许其他线程运行。

  

死锁是程序设计的bug,在设计程序时要避免双方互相持有对方锁的情况。需要说明的是,本实验使用synchronized嵌套的代码结构来实现死锁,其实不使用嵌套的synchronized代码结构也会出现死锁,与嵌套不嵌套没有任何的关系。只要互相等待对方释放锁,就有可能出现死锁。

以上是关于Java并发编程 - 一个简单的死锁示例和死锁的检查的主要内容,如果未能解决你的问题,请参考以下文章

Java并发编程实战读书笔记之死锁

Java并发屏障示例死锁

java死锁示例及其发现方法

Java并发编程死锁

《java并发编程实战》读书笔记8--死锁,性能与可伸缩性,锁粒度锁分解锁分段

Java并发编程实战 04死锁了怎么办?