b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

Java多线程7: 死锁

电脑杂谈  发布时间:2020-04-12 23:26:30  来源:网络整理

java多线程避免死锁_java多线程避免死锁_线程死锁

前言

Deadlock撰写了另一篇文章,因为这是一个必须引起注意的严重问题. 这并不是夸大死锁的风险. 尽管锁通常会保留很短的时间,但作为商业产品的应用程序可能每天执行数十亿次锁获取->释放操作,只要这些数十亿次操作期间发生错误java多线程避免死锁,就可能导致程序中出现死锁,即使它通过了压力测试,也无法找到所有潜在的死锁.

死锁

一个经典的多线程问题.

当一个线程永久持有一个锁而其他线程试图获取该锁时,众所周知,它们将永远被阻塞. 如果线程A持有锁L并希望获取锁M,而线程B持有锁M并希望获取锁L,则这两个线程将永远等待. 这是最简单的死锁形式.

在系统的设计中,考虑了死锁的监视和从死锁中的恢复. 如果检测到一组事务具有死锁,它将选择一个受害者并放弃该事务. Java虚拟机在解决死锁问题方面不如强大. 当一组Java线程死锁时,这两个线程将永远无法再使用,并且由于这两个线程持有两个锁,因此这两个同步的代码/代码块将不再运行,除非终止应用程序并重新启动

死锁是一个设计错误,问题更加模糊. 但是,死锁的影响很少立即出现. 一个类可能是死锁的,这并不意味着每次都会发生死锁. 这只是意味着有可能. 当发生死锁时,它通常处于最坏的情况下,即高负载.

java多线程避免死锁_java多线程避免死锁_线程死锁

这是一个生成死锁并演示如何分析这是死锁的简单代码:

public class DeadLock
{
    private final Object left = new Object();
    private final Object right = new Object();
    
    public void leftRight() throws Exception
    {
        synchronized (left)
        {
            Thread.sleep(2000);
            synchronized (right)
            {
                System.out.println("leftRight end!");
            }
        }
    }
    
    public void rightLeft() throws Exception
    {
        synchronized (right)
        {
            Thread.sleep(2000);
            synchronized (left)
            {
                System.out.println("rightLeft end!");
            }
        }
    }
}

请注意,必须有“ Thread.sleep(2000)”使线程进入睡眠状态,否则一个线程正在运行,而另一个线程尚未运行. 首先运行的线程很可能已经连续获得了两个锁. 编写两个线程以分别调用它们:

public class Thread0 extends Thread
{
    private DeadLock dl;
    
    public Thread0(DeadLock dl)
    {
        this.dl = dl;
    }
    
    public void run()
    {
        try
        {
            dl.leftRight();
        } 
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

public class Thread1 extends Thread
{
    private DeadLock dl;
    
    public Thread1(DeadLock dl)
    {
        this.dl = dl;
    }
    
    public void run()
    {
        try
        {
            dl.rightLeft();
        } 
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

编写一个主函数调用:

public static void main(String[] args)
{
    DeadLock dl = new DeadLock();
    Thread0 t0 = new Thread0(dl);
    Thread1 t1 = new Thread1(dl);
    t0.start();
    t1.start();
    while(true);   
}

线程死锁_java多线程避免死锁_java多线程避免死锁

关于结果,没有结果,因为死锁,所以不会打印任何语句. 下面演示了如何定位死锁问题:

1,jps获取当前Java虚拟机进程的pid

2. jstack打印堆栈. 在jstack所打印内容的末尾,我们实际上已经报告发现了死锁,但是由于我们正在分析死锁的原因,而不是直接得出此处存在死锁的结论,因此,请别理它,看看在上一部分

首先解释每个部分的含义,以“ Thread-1”为例:

(1)“线程1”表示线程名称

线程死锁_java多线程避免死锁_java多线程避免死锁

(2)“ prio = 6”表示线程优先级

(3)“ tid = 00000000497cec00”表示线程ID

(4)nid = 0x219c

与线程相对应的本地线程ID. 下面说明了这一关键点. 因为Java线程由附加到Java虚拟机的本地线程运行,所以本地线程实际上是在执行Java线程代码,只有本地线程才是真正的线程实体. 在Java代码中创建一个线程,虚拟机将在运行时创建一个相应的本地线程,并且该本地线程是真实的线程实体. 在Linux环境中,可以使用“ top -H -p JVM进程ID”来查看JVM进程下本地线程(也称为LWP)的信息. 请注意,此本地线程用十进制表示java多线程避免死锁,而nid用十六进制表示. ,只需对其进行转换,对应于0x219c的本地线程ID应该为8604.

(5)“ [0x000000004a3bf000..0x000000004a3bf790]”表示线程占用的内存地址

(6)“ java.lang.Thread.State: BLOCKED”指示线程的状态

在解释了每个部分的含义之后,可以看到Thread-1处于BLOCKED状态,而Thread-0处于BLOCKED状态. 分析这两个线程:

java多线程避免死锁_线程死锁_java多线程避免死锁

(1)线程1已获得锁0x000000003416a4e8,并正在等待锁0x000000003416a4d8

(2)线程0获得了锁0x000000003416a4d8,并正在等待锁0x000000003416a4e8

由于两个线程都在等待获取对方持有的锁,所以它们永远都在等待.

3. 注意使用Eclipse / MyEclipse. 如果不单击控制台上的红色框以终止它,而是右键单击->运行方式-> 1 Java应用程序,则此过程将始终存在. 此时,您可以使用taskkill命令终止尚未终止的进程:

如何避免死锁

由于可能存在死锁,让我们来谈谈如何避免死锁.

1. 让程序一次最多获得一个锁. 当然,在多线程环境中,这种情况通常是不现实的

2. 设计时请清楚考虑锁的顺序,并尝试减少嵌入式锁交互的次数

3. 由于死锁是由两个线程无限期地等待对方持有的锁引起的,因此只要存在等待时间的上限即可. 当然,同步没有此功能,但是我们可以在Lock类中使用tryLock方法来尝试获取锁. 此方法可以指定一个超时时间,并在返回此时间限制后返回失败消息


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-173485-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...