塌鼻子巴巴鲁 2018-05-24 12:52 采纳率: 45.5%
浏览 584
已采纳

关于Java死锁原理,苦想好久都不明白,希望大佬们帮忙!谢谢!

下面是一个Java的死锁模拟程序

package demo;

public class DeadLockDemo {

     public static void main(String[] args) {
         DeadLock dead = new DeadLock();
         Thread t0 = new Thread(dead);
         Thread t1 = new Thread(dead);
         t0.start();
         t1.start();
       }
}
package demo;

public class DeadLock implements Runnable {
     private int i = 0;
     public void run(){
       while(true){
         if(i%2==0){
           //先进入A同步,再进入B同步
           synchronized(LockA.locka){
             System.out.println(Thread.currentThread().getName()+"   if...locka");
             synchronized(LockB.lockb){
               System.out.println(Thread.currentThread().getName()+"   if...lockb");
             }
           }
         }else{
           //先进入B同步,再进入A同步
           synchronized(LockB.lockb){
             System.out.println(Thread.currentThread().getName()+"   else...lockb");
             synchronized(LockA.locka){
               System.out.println(Thread.currentThread().getName()+"   else...locka");
             }
           }
         }
         i++;
       }
     }
}
package demo;

public class LockA {
     private LockA(){}

     public  static final LockA locka = new LockA();
}
package demo;

public class LockB {
     private LockB(){}

     public static final LockB lockb = new LockB();
}

运行某一次的输出结果为:
Thread-0 if...locka
Thread-0 if...lockb
Thread-1 if...locka
Thread-1 if...lockb
Thread-1 else...lockb
Thread-0 if...locka
我想问的是: 1.两个线程Thread-0和Thread-1在方法run中调用的i是不是同一个i?
2.如果是同一个i,那么结果中当输出Thread-1 else...lockb后i的值应该是奇数,还没执行后面的i++,此时线程Thread-0抢占资源运行,由于i为奇数,应该走else语句,输出else...lockb才对啊,为什么最后会输出Thread-0 if...locka?
并且,输出结果的前四个不应该都是if....才对啊?
3.如果不是同一个i,又为什么不是呢?调用同一个对象,i应该是同一个才对啊?

  • 写回答

2条回答 默认 最新

  • DengDengLei 2018-05-24 14:13
    关注

    是同一个i,有一种情况你忽略了:
    线程0第一次进入if(i%2==0)判断为true后,还未来得及执行后面的语句,然后此时线程1抢占资源,因为此时线程0还没来得及执行i++,因此对线程1而言i还是0。
    你可以添加更多输出语句查看线程的执行情况:
    1、在i%2==0的判断后面添加输出:if(i%2==0){System.out.println(Thread.currentThread().getName()+" here");...}
    2、在i++前添加输出:System.out.println(Thread.currentThread().getName()+" i++"); i++;

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?