2016.12.07 死锁

如果有建议或者自己的想法,请在下方评论,我们一起探讨(本人一只菜狗)

在二个月之前面试的时候,我面试碰到一个问题,

人家问我什么是死锁?

答:两个或者多个进程在执行过程中,互相争抢资源,比如说a进程需要b进程才能往下进行,但是b进程也在等着a进程才能执行,所以就互相等待,若没有外力,就这样一直等待下去(此时称系统处于死锁转台或者系统产生了死锁,这些永远在互相等待的进程称为死锁进程)

什么是进程,和线程的区别?

答:可以说一个进程中包含多个线程,线程只是一个进程的不同执行路径,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉

死锁的简单例子?

答:线程的同步化可能会造成死锁,死锁发生在两个线程相互持有对方正在等待的东西(实际是两个线程共享的东西)。只要有两个线程和两个对象就可能产生死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
* 一个简单的死锁类
* 当DeadLock类的对象flag==1时(td1),先锁定o1,睡眠500毫秒
* 而td1在睡眠的时候另一个flag==0的对象(td2)线程启动,先锁定o2,睡眠500毫秒
* td1睡眠结束后需要锁定o2才能继续执行,而此时o2已被td2锁定;
* td2睡眠结束后需要锁定o1才能继续执行,而此时o1已被td1锁定;
* td1、td2相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。
*/ 
public  class  DeadLock implements  Runnable { 
     public  int  flag = 1
     //静态对象是类的所有对象共享的 
     private  static  Object o1 = new  Object(), o2 = new  Object(); 
     @Override 
     public  void  run() { 
         System.out.println( "flag="  + flag); 
         if  (flag == 1 ) { 
             synchronized  (o1) { 
                 try 
                     Thread.sleep( 500 ); 
                 } catch  (Exception e) { 
                     e.printStackTrace(); 
                
                 synchronized  (o2) { 
                     System.out.println( "1" ); 
                
            
        
         if  (flag == 0 ) { 
             synchronized  (o2) { 
                 try 
                     Thread.sleep( 500 ); 
                 } catch  (Exception e) { 
                     e.printStackTrace(); 
                
                 synchronized  (o1) { 
                     System.out.println( "0" ); 
                
            
        
    
   
     public  static  void  main(String[] args) { 
           
         DeadLock td1 = new  DeadLock(); 
         DeadLock td2 = new  DeadLock(); 
         td1.flag = 1
         td2.flag = 0
         //td1,td2都处于可执行状态,但JVM线程调度先执行哪个线程是不确定的。 
         //td2的run()可能在td1的run()之前运行 
         new  Thread(td1).start(); 
         new  Thread(td2).start(); 
   
    
}

怎么避免死锁?
 
 
作者:毛林 链接:https://www.zhihu.com/question/29268623/answer/44063281 来源:知乎 著作权归作者所有,转载请联系作者获得授权。
一. 理论上死锁的4个必要条件
  1. 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
  2. 请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
  3. 非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
  4. 循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源
二. 个人经验总结的充分条件,***不保证完全并且严谨***
  1. 在代码中,存在同时获取至少2个锁A/B的场景,并且这样的代码出现超过1次。
  2. 上面提到的两段不同代码对同样两个锁获取顺序不一致。
  3. 上面提到的两端代码会运行在不同的线程/进程中。
以上3个情况同时出现,死锁必然发生,只是看概率问题。 三. 两大解决办法
  1. 打破上述3种情况同时出现的:
    1. 避免同一时刻持有两把锁,在可能的情况下改为先持有A,释放后再申请B。
    2. 如果上述情况无法避免,确保会被同时持有的锁的申请顺序和释放顺序在任何地方都一致。
  2. 允许出现死锁,当检测到死锁后触发解锁机制:例如申请到A后,再申请B,500ms后发现申请失败,回头去释放A,解除死锁。
  3. 避免使用锁,有多种手段可以使用:Lock-free无锁数据结构,消息队列,管道等等。
PS,我个人倾向“尽量避免使用锁”,即使在多线程环境下编写程序。 ------------------------------------------------------------------------------------------ sorry,没注意看到描述中说的是数据库表死锁问题。 数据库的死锁原理和我前面提到的相通,数据库软件也是一个程序,表对于它来说是一个某时需要独占的资源。数据库编程我不太熟悉,仅就推理做下列回答:
  1. 表的锁定通常是由插入删除造成的,修改数据仅引起行锁定(不确定,我都说了我对数据库不熟。。。)
  2. 检查是否在一条语句或同一事务中对多个表进行了写操作,并且访问顺序还不一致。
  3. 以事务方式更新表的话记的必须要commit或者rollback。
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孔明兴汉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值