1cming
V2EX  ›  Java

面试:“必然”引起“死锁”的一段代码。

  •  
  •   1cming · May 23, 2018 · 10417 views
    This topic created in 3085 days ago, the information mentioned may be changed or developed.

    这个必然让我有点疑惑,A 等待 B,B 等待 A 这种还有意外会发生吗?求教。

    Supplement 1  ·  May 24, 2018
    大家可以看一下#15 @ryd994 还有 #13 @geelaw 还有 #20 @mashiro233 这几位朋友的回答,再次感谢大家。
    QK8wAUi0yXBY1pT7
    QK8wAUi0yXBY1pT7
    May 23, 2018
    1
    建议多翻一下《操作系统》和语文书。
    zhengxiaowai
    zhengxiaowai
    May 23, 2018
    2
    分分钟 100 个例子
    luojianxhlxt
    luojianxhlxt
    May 23, 2018
    3
    数据库里面很多,代码倒是没咋接触过
    Arsenal16
    Arsenal16
    May 23, 2018
    4
    老哥看一下 实战 Java 高并发程序设计 4.5 有关死锁的问题 那一章节
    百分百死锁啊, 讲的还是挺详细的.
    这里贴代码排版会有问题, 老哥你可以直接去看一下书
    ldd
    ldd
    May 23, 2018
    5
    这个是肯定会引起死锁的,这种情况在多节点的 RAC 上见得比较多,比如需要同时更新多个表时,不同的业务对这几张表的更新顺序不一致,就容易引发死锁。

    不过像 Oracl 这样企业级的软件都会有自动的解锁行为,有个时间阈值,超过后就会牺牲掉一个事物,达到解锁目的。所以实际业务中几乎不会出现长时间的死锁。
    q397064399
    q397064399
    May 23, 2018
    6
    死锁的四个必要条件
    0Y89tX3MgR4I
    0Y89tX3MgR4I
    May 23, 2018 via Android❤️6
    7
    是不是我语文不好,看不懂楼主想表达什么
    1cming
    1cming
    OP
    May 23, 2018
    8
    @Arsenal16 好的谢谢我下午看一下
    GuuJiang
    GuuJiang
    May 23, 2018
    9
    methodA() {
    synchronized(lockA) {
    Thread.sleep(10000);
    synchronized(lockB) {
    ...
    }
    }
    }

    methodB() {
    synchronized(lockB) {
    Thread.sleep(10000);
    synchronized(lockA) {
    ...
    }
    }
    }

    拿去不谢
    1cming
    1cming
    OP
    May 23, 2018
    10
    @Arsenal16 这里我刚才看了 他举的例子也并没有特别的地方 难道是我多想了?


    @hxd
    @zhengxiaowai
    @ldd
    @0Y89tX3MgR4I
    对方的原话大意是:写一个“必然”会出现死锁的一段代码,我面过很多人,他们写的都不是严格意义上的死锁,都被我挑出来很多刺。
    鉴于此,我在思考是否有代码之外比如 OS 上的一些考虑?
    1cming
    1cming
    OP
    May 23, 2018
    11
    对方是某一线大厂资深级别的技术 leader,感觉事情并不简单,所以才会来 V 站一问,下午我会更新一下结果。
    startar
    startar
    May 23, 2018 via Android
    12
    线程 1:
    锁 A
    锁 B
    干活
    释放 B
    释放 A

    线程 2:
    锁 B
    锁 A
    干活
    释放 A
    释放 B

    这样就会死锁啊
    geelaw
    geelaw
    May 23, 2018 via iPhone❤️2
    13
    用睡眠并不会必然导致死锁,只是以非常高的概率导致而已。

    一个简单的方法是这样:线程 1 把自己的 handle 存在全局变量的 1 里,然后启动线程 2 并获得其 handle,然后等待这个 handle (等线程 2 结束);线程 2 的惟一工作是等待线程 1 的 handle。很容易证明,无论怎样调度,一定会进入死锁。

    在没有单进程多线程概念的操作系统(如传统 UNIX ),你需要通过进程的等待完成类似任务。
    ryd994
    ryd994
    May 23, 2018 via Android
    14
    非重入锁重入就是保证死锁
    ryd994
    ryd994
    May 23, 2018 via Android❤️4
    15
    多线程的话可以用信号量
    1 锁 A,2 锁 B
    1 给 2 发信号,2 给 1 发信号
    等到收到信号,1 锁 B,2 锁 A
    因为各自没有取得锁前不会发出信号,因此收到信号就可以保证死锁
    信号量可以使用操作系统的信号量,也可以使用原子变量简单实现

    这不是一道考锁的题,而是一道考分布式系统事件排序的题

    @GuuJiang 如果因为进程调度,method B 被调度到 A 完成之后才执行呢?正常调度系统会考虑公平性,所以很难发生。但这并不是前提条件。
    roychan
    roychan
    May 23, 2018
    16
    写个哲学家就餐问题不就 ok 了。。。
    John60676
    John60676
    May 23, 2018
    17
    哲学家就餐 加一
    0Y89tX3MgR4I
    0Y89tX3MgR4I
    May 23, 2018
    18
    @ryd994 嗯,两个锁和一个条件变量就好了
    nullcc
    nullcc
    May 23, 2018
    19
    thread 1:
    acquire(A)
    acquire(B)

    thread 2:
    acquire(B)
    acquire(A)

    Bomb !!!
    mashiro233
    mashiro233
    May 23, 2018❤️1
    20
    楼上的一些朋友回答的很好了。
    调度器的运作原理对应用层来说应该是未定义的。代码中启动 A,B 两个线程,调度器可以不保证 A 在 B 之前或者之后启动,启动了也不保证每个线程能用多少 cpu 时间。
    ryd994
    ryd994
    May 23, 2018 via Android
    21
    @roychan
    @John60676 哲学家就餐只是可能死锁,并不能保证死锁。如果某个哲学家手特别快,在别人反应过来前就左右都抢到了呢?有调度器在,就不能忽略这种可能。

    @nullcc A 特别快,直接把两个锁都拿到了
    1cming
    1cming
    OP
    May 23, 2018
    22
    @geelaw
    @ryd994
    感谢二位,这个是我想要的答案。
    zhangchioulin
    zhangchioulin
    May 23, 2018
    23
    iOS 中 OSSpinLock 优先级反转也会死锁
    USNaWen
    USNaWen
    May 23, 2018
    24
    互斥
    不可剥夺
    请求和保持
    循环等待
    tangweihua163
    tangweihua163
    May 23, 2018
    25
    必然死锁,一个线程内才行,连续多次试锁同一资源?多个线程就不是必然
    zhengxiaowai
    zhengxiaowai
    May 23, 2018
    26
    @1cming 一个很经典的案例:哲学家就餐问题
    Finest
    Finest
    May 23, 2018
    27
    线程 A:
    l1.lock()
    while(true)
    l2.lock()

    线程 B:
    l2.lock()
    while(true)
    l1.lock()
    KIDJourney
    KIDJourney
    May 23, 2018
    28
    l1 = lock()
    l1.lock()
    l1.lock()

    这不就死锁了。
    tempdban
    tempdban
    May 23, 2018 via Android
    29
    上了一课
    ryd994
    ryd994
    May 24, 2018 via Android❤️1
    30
    @KIDJourney 你这个就叫不可重入锁重入
    如果是重入锁,同一个线程锁两次是允许的
    另外也可以设置如果重入则报错
    jedihy
    jedihy
    May 24, 2018
    31
    对,这不是考 OS,这是靠分布式系统与算法
    ebingtel
    ebingtel
    May 24, 2018
    32
    @q397064399 对头 lz 描述的情况 只满足了一个
    lerosua
    lerosua
    May 27, 2018
    33
    邮局寄个包裹给你, 要你身份证就能给你,但你的身份证就在包裹里~ 所以死锁了~
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1425 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 92ms · UTC 22:43 · PVG 06:43 · LAX 14:43 · JFK 17:43
    ♥ Do have faith in what you're doing.