关于同步_死锁_why

能否写一个容易产生死锁的程序?

 

死锁的现象:程序挂着不动了

死锁的本质:所有的钥匙都被占用了,导致双方都失去代码的执行权;

 

线程安全隐患:一个线程还没执行完必须同步的代码,cpu就把运行权交给另一个共享代码的线程了,导致错乱;

解决方案:把该同步完成的代码封装到一个{}中,再没有执行完之前,其他线程没有权利读取和执行该{}中的代码;

同步安全原理:给需要同步的代码加个锁(synchronized),给锁配一把钥匙(Object / this / .class ),谁在执行该代码,谁就得到对应的钥匙;

                           因为只有一把钥匙,所以其他线程没有钥匙,就打不开锁,就得不到锁中的代码,也就是没权利执行锁中的代码,这样就安全了;

 

有可能产生的问题:

                   当A线程执行到一半,失去cpu的执行权,B线程得到cpu执行权,B把锁中的代码执行到一半发现里边有一部分代码加了锁,可是钥匙在A线程代码的锁上,这时,B线程可住了,需要得到A线程执行完剩下的代码后才能拿到钥匙,杯具的事情来了,因为这时B线程锁上的钥匙刚好就是A线程剩下的代码的锁的钥匙,各持一把钥匙,而且钥匙都拿不出来,因为双方锁中的代码都没执行完;(这时就是死锁)

 

写一个死锁的代码:

思路:让两条线程,各持对方需要的钥匙;

                        1,A线程和B线程的run方法中的代码加上嵌套锁;

                        2,两条线程的嵌套锁共用两把钥匙;

                        3,B线程的外套锁共用A线程内套锁的钥匙,内套锁共用A线程的外套锁的钥匙;

 

代码体现:

public class DeadLockTest {

 /**
  * 面试:写一个死锁事例
  * 两锁嵌套
  *
  * 同步安全的原理:
  * 当A线程在执行一半的代码后失去执行权,那么共享这些代码的其他线程,没有权利执行这些代码;
  * 只有当我把同步中的所有代码执行完,其他线程才能进来执行;
  *
  * 一锁不能二用,对象不可二用;
  *
  */
 public static class DeadLock implements Runnable {
  //成员变量 
  private boolean flag;
  //构造函数
  DeadLock(boolean flag){
   this.flag = flag;
  }
  //成员函数
  public void run(){
   //if else 制造双体
   if(flag){
    while(true){
     synchronized(MyLock.keyb){
      System.out.println("Thread 1 拿着 keyb");
      synchronized(MyLock.keya){
       System.out.println("Thread 1 拿着 keya");
       System.out.println("Thread 1 释放 keya");
      }
      System.out.println("Thread 1 释放 keyb");
     }
    }
   }
   else{
    while(true){
     synchronized(MyLock.keya){
      System.out.println("Thread 2 拿着 keya");
      synchronized(MyLock.keyb){
       System.out.println("Thread 2 拿着 keyb");
       System.out.println("Thread 2 释放 keyb");
      }
      System.out.println("Thread 2 释放 keya");
     }
    }//复制死锁时,最后一部分打印结果:
      /*
     Thread 2 拿着 keya
     Thread 2 拿着 keyb
     Thread 2 释放 keyb
     Thread 2 释放 keya
     Thread 2 拿着 keya    // 2拿a不放
     Thread 1 拿着 keyb */ // 1拿b不放   两把钥匙被两个人拿到时,就死了
   } 
  }
 }
 //准备两个锁的钥匙
 public static class MyLock{
  static Object keya = new Object();
  static Object keyb = new Object();
 }

 public static void main(String[] args) {
  // 建立事物对象
  DeadLock d1 = new DeadLock(true);
  DeadLock d2 = new DeadLock(false);
  // 建立线程,把对象导入线程
  Thread t1 = new Thread(d1);
  Thread t2 = new Thread(d2);
  // 启动线程
  t1.start();
  t2.start();
  

 }

}

 

                   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值