Java之线程死锁

版权声明:欢迎转载,转载请注明出处哦! https://blog.csdn.net/qq_41647999/article/details/88542529

死锁在类中只是有可能发生,并不是每次都发生,但是死锁是一个非常严重的一个问题,必须引起重视!

一、 什么是死锁?

 概念

不同的线程分别占用对方的同步资源不放弃,都在等待对方放弃自己需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。

补充

在数据库系统的设计中考虑了监测死锁以及从死锁中恢复,数据库如果监测到了一组事务发生了死锁时,将选择一个牺牲者并放弃这个事务。Java虚拟机解决死锁问题方面并没有数据库这么强大,当一组Java线程发生死锁时,这两个线程就永远不能再使用了,并且由于两个线程分别持有了两个锁,那么这两段同步代码/代码块也无法再运行了----除非终止并重启应用。

举个例子

当两个在一起吃饭的时候,只有一双筷子,此时只能使用着一双筷子来吃饭,你拿着这双筷子不放手,另外一个人也拿着不放手,都在等对方放手。此时的这种状态就形成了死锁。

 三、 死锁的问题

处理线程同步时最容易出现。

下面是老师给的一个例子,运行起来就直接可以看到死锁的效果了(一直卡在运行界面)。

 public class TestDeadLock {
    /*
    定义为static直接使用
     */
        static StringBuffer sb1 = new StringBuffer();
        static StringBuffer sb2 = new StringBuffer();
        public static void main(String[] args) {
            new Thread() {
                public void run() {
                    synchronized (sb1) {
                        // sleep让死锁的效果更加明显
                        try {
                            Thread.currentThread().sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        sb1.append("A");
                        synchronized (sb2) {
                            sb2.append("B");
                            System.out.println(sb1);
                            System.out.println(sb2);
                        }
                    }
                }
            }.start();

            new Thread() {
                public void run() {
                    synchronized (sb2) {
                        try {
                            Thread.currentThread().sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        sb1.append("C");
                        synchronized (sb1) {
                            sb2.append("D");
                            System.out.println(sb1);
                            System.out.println(sb2);
                        }
                    }
                }
            }.start();
        }
    }

解释一下这里出现死锁的原因:

程序进入第一个new Thread代码块中的run()方法之后,先握住sb1这把锁,执行到sleep,此时如果有其它线程也正在执行,就很有可能会被其它线程抢到CPU的执行权。这里有第二个线程(假设这个线程在10ms中抢到CPU的执行权的几率为100%),开始执行这里的代码块,当程序握住sb2这把锁的时候sleep一下。此时第一个线程又继续执行,发现此时也是sb2这把锁。于是出现了“你不让我,我不让你,都认为对方会放手” 的问题,也就是死锁。

二、 如何解决死锁?

1、 专门的算法、原则。

      1) 让程序每次至多只能获得一个锁。当然,在多线程环境下,这种情况通常并不现实。

      2) 设计时考虑清楚锁的顺序,尽量减少嵌在的加锁交互数量。

      3) 既然死锁的产生是两个线程无限等待对方持有的锁,那么只要等待时间有个上限不就好了。

2、 尽量减少同步资源的定义

 

 

猜你喜欢

转载自blog.csdn.net/qq_41647999/article/details/88542529