美文网首页程序员
Java多线程-死锁的出现和解决

Java多线程-死锁的出现和解决

作者: Java红茶 | 来源:发表于2017-10-20 21:11 被阅读0次

Java多线程-死锁
什么是死锁?

死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不能正常运行.形象的说就是:一个宝藏需要两把钥匙来打开,同时间正好来了两个人,他们一人一把钥匙,但是双方都再等着对方能交出钥匙来打开宝藏,谁都没释放自己的那把钥匙.就这样这俩人一直僵持下去,直到开发人员发现这个局面.

导致死锁的根源在于不适当地运用“synchronized”关键词来管理线程对特定对象的访问.“synchronized”关键词的作用是,确保在某个时刻只有一个线程被允许执行特定的代码块,因此,被允许执行的线程首先必须拥有对变量或对象的排他性访问权.当线程访问对象时,线程会给对象加锁,而这个锁导致其它也想访问同一对象的线程被阻塞,直至第一个线程释放它加在对象上的锁.

对synchronized不太了解的话请点击这里

举个例子

死锁的产生大部分都是在你不知情的时候.我们通过一个例子来看下什么是死锁.

1.synchronized嵌套.

synchronized关键字可以保证多线程再访问到synchronized修饰的方法的时候保证了同步性.就是线程A访问到这个方法的时候线程B同时也来访问这个方法,这时线程B将进行阻塞,等待线程A执行完才可以去访问.这里就要用到synchronized所持有的同步锁.具体来看代码:

//首先我们先定义两个final的对象锁.可以看做是共有的资源.
 final Object lockA = new Object();
 final Object lockB = new Object();
//生产者A
  class  ProductThreadA implements Runnable{
      @Override
      public void run() {
//这里一定要让线程睡一会儿来模拟处理数据 ,要不然的话死锁的现象不会那么的明显.这里就是同步语句块里面,首先获得对象锁lockA,然后执行一些代码,随后我们需要对象锁lockB去执行另外一些代码.
          synchronized (lockA){
          //这里一个log日志
              Log.e("CHAO","ThreadA lock  lockA");
              try {
                  Thread.sleep(2000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              synchronized (lockB){
               //这里一个log日志
                  Log.e("CHAO","ThreadA lock  lockB");
                  try {
                      Thread.sleep(2000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }

              }
          }
      }
  }
  //生产者B
  class  ProductThreadB implements Runnable{
  //我们生产的顺序真好好生产者A相反,我们首先需要对象锁lockB,然后需要对象锁lockA.
      @Override
      public void run() {
          synchronized (lockB){
           //这里一个log日志
              Log.e("CHAO","ThreadB lock  lockB");
              try {
                  Thread.sleep(2000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              synchronized (lockA){
               //这里一个log日志
                  Log.e("CHAO","ThreadB lock  lockA");
                  try {
                      Thread.sleep(2000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }

              }
          }
      }
  }
  //这里运行线程
ProductThreadA productThreadA = new ProductThreadA();
ProductThreadB productThreadB = new ProductThreadB();

      Thread threadA = new Thread(productThreadA);
      Thread threadB = new Thread(productThreadB);
      threadA.start();
      threadB.start();

分析一下,当threadA开始执行run方法的时候,它会先持有对象锁localA,然后睡眠2秒,这时候threadB也开始执行run方法,它持有的是localB对象锁.当threadA运行到第二个同步方法的时候,发现localB的对象锁不能使用(threadB未释放localB锁),threadA就停在这里等待localB锁.随后threadB也执行到第二个同步方法,去访问localA对象锁的时候发现localA还没有被释放(threadA未释放localA锁),threadB也停在这里等待localA锁释放.就这样两个线程都没办法继续执行下去,进入死锁的状态. 看下运行结果:

10-20 14:54:39.940 18162-18178/? E/CHAO: ThreadA lock  lockA
10-20 14:54:39.940 18162-18179/? E/CHAO: ThreadB lock  lockB

当不会死锁的时候应该是打印四条log的,这里明显的出现了死锁的现象.

死锁出现的原因

当我们了解在什么情况下会产生死锁,以及什么是死锁的时候,我们在写代码的时候应该尽量的去避免这个误区.产生死锁必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生.

• 互斥条件:线程要求对所分配的资源进行排他性控制,即在一段时间内某 资源仅为一个进程所占有.此时若有其他进程请求该资源.则请求进程只能等待.

• 不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的线程自己来释放(只能是主动释放).

• 请求和保持条件:线程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他线程占有,此时请求线程被阻塞,但对自己已获得的资源保持不放.

• 循环等待条件:存在一种线程资源的循环等待链,链中每一个线程已获得的资源同时被链中下一个线程所请求。

死锁的解决方法

说实话避免死锁还得再自己写代码的时候注意一下.这里引用别人的解决方法,不过我对于这些解决方法不是太懂,讲的太含糊没有具体的实例.
java交流669823128

相关文章

  • Java多线程-死锁的出现和解决

    Java多线程-死锁什么是死锁? 死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释...

  • 中级09 - Java多线程初步

    中级09 - Java多线程初步 介绍多线程带来的问题,以及基本解决方案。 竞争条件带来的数据错误问题 死锁的原...

  • Java自学-多线程 死锁

    Java 演示多线程死锁 当业务比较复杂,多线程应用里有可能会发生死锁 步骤 1 : 演示死锁 线程1 首先占有对...

  • 照本宣科的问题

    3条你遵循的多线程最佳实践三条最佳实践我觉得大多数Java程序员都应该遵循: 如何避免死锁?Java多线程中的死锁...

  • 多线程分析——死锁代码demo

    前言 本文主要是对Java多线程死锁代码demo的分析,对其过程以及死锁进行了大致的概括,希望对大家有帮助。 死锁...

  • 使用JDK自带的工具jstack找出造成运行程序死锁的原因

    Java多线程编程也是Java面试中经常考察的内容。刚接触Java多线程编程的朋友们,可能会不慎写出一些会导致死锁...

  • jstack命令:教你如何排查多线程问题

    这是之前的一个死锁案例: 一个多线程死锁案例,如何避免及解决死锁问题? 如程序中发生这样的死锁问题该如何排查呢?我...

  • 为何出现死锁

    为何出现 jps 和 jstack 工具查看死锁如何解决

  • Synchronized关键字详解2(对非object持锁)

    4.死锁:同步方法容易造成死锁。Java线程死锁是一个经典的多线程问题,因为不同的线程都在等待根本不可能被释放的锁...

  • 18 多线程死锁

    多线程死锁产生的原因:在同步中嵌套同步,会出现死锁的现象。 查找到当前JVM环境变量C:\Program File...

网友评论

    本文标题:Java多线程-死锁的出现和解决

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