死锁

作者: 守住阳光 | 来源:发表于2018-07-05 16:47 被阅读0次

一、什么是死锁

        并发编程的本质是将串行执行的代码编程并行执行。并发编程的目的是为了加快程序的运行速度,但是如果使用不当,不仅不会带来速度的提升,反而变得更慢,甚至造成程序出现异常。其中,死锁就是一种对并发编程带来的挑战。

        什么是死锁?

        死锁是指多个线程循环等待他方占有的资源而无限制地僵持下去的局面。如果没有外力的作用,那么死锁涉及到的各个线程都将永远处于阻塞状态。如下代码时一个死锁的经典例子:

public class DeadLockDemo {

        privat static String A = "A";

        private static String B = "B";

        public static void main(String[] args) {

                new DeadLockDemo().deadLock();

        }

        private void deadLock() {

            Thread t1 = new Thread(new Runnable() {

                    @Override

                    publicvoid run() {

                        synchronized (A) {

                            try { 

                                   Thread.currentThread().sleep(2000);

                             } catch (InterruptedException e) {

                                    e.printStackTrace();

                             }

                              synchronized (B) {

                                    System.out.println("1");

                                }

                        }

                }

        });

        Thread t2 = new Thread(new Runnable() {

                    @Override

                    publicvoid run() {

                        synchronized (B) {

                                synchronized (A) {

                                        System.out.println("2");

                                    }

                        }

                    }

        });

        t1.start();

        t2.start();

     }

}

        这段代码只是演示死锁的场景,在现实中可能不会写出这样的代码。但是,在一些更为复杂的场景中,你可能会遇到这样的问题,比如t1拿到锁之后,因为一些异常情况没有释放锁(死循环)。又或者是t1拿到一个数据库锁,释放锁的时候抛出了异常,没释放掉。

        还有一个经典的业务场景:比如银行转账,在转账执行中,你可能会先锁住转出的账户,将款扣掉,然后锁住转入的账户,将金额增加。从表面上看,我们总是先锁转出账户,然后锁住转入账户,应该是没有问题的。但是张三向李四转钱,转出账户是张三的账户,转入的账户是李四,这一线程先获取张三的账户为对象锁,然后再获取李四的账户为对象锁。同时李四向张三转钱,转出账户是李四的账户,转入的账户是张三的账户,这一线程需要先获取李四的账户的账户为对象锁,然后获取张三的账户为对象锁,张三的账户为对象锁的锁已经被获取了。上述过程就会造成死锁。

二、如何避免死锁?

    1、避免一个线程同时获取多个锁。

    2、避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。

    3、尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。

    4、对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

相关文章

  • 死锁

    线程饥饿死锁 锁顺序死锁 动态锁顺序死锁通过锁顺序来避免死锁 避免死锁

  • 死锁

    第11章:死锁和进程通信 死锁概念 死锁处理方法 死锁预防(Deadlock Prevention) 死锁避免(D...

  • java多线程笔记

    产生死锁的四个必要条件 处理死锁的基本方法 死锁预防 死锁避免 死锁检测 死锁解除 https://blog.cs...

  • [现代操作系统]--死锁

    table of content 死锁定义 死锁建模-- 资源分配图 处理死锁鸵鸟算法检测并恢复死锁检测死锁恢复利...

  • Java-多线程(四)死锁

    死锁 死锁示例

  • Java死锁

    什么是死锁 死锁检测 产生死锁的四个必要条件 如何避免死锁 死锁 死锁,指两个或多个线程之间,由于互相持有对方需要...

  • java并发--java死锁

    本篇结构: 前言 什么是死锁 产生死锁的必要条件 死锁的代码示例 死锁排查 如何避免死锁 总结 一、前言 今天被问...

  • Java多线程之死锁(Deadlock)及死锁避免(Deadlo

    线程死锁(Thread Deadlock) 数据库死锁(Database Deadlocks) 死锁避免 (Dea...

  • JavaEE面试题总结 Day39 2018-12-29

    什么是线程死锁?死锁如何产生?如何避免线程死锁? 死锁的介绍: 线程死锁是指由于两个或者多个线程互相持有对方所需要...

  • Java并发之嵌套管程锁死(Nested Monitor Loc

    嵌套管程死锁是如何发生的 具体的嵌套管程死锁的例子 嵌套管程死锁 vs 死锁 嵌套管程锁死类似于死锁, 下面是一个...

网友评论

      本文标题:死锁

      本文链接:https://www.haomeiwen.com/subject/ufvpuftx.html