AQS 公平锁真的完全公平吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
ceshi123
V2EX    Java

AQS 公平锁真的完全公平吗?

  •  
  •   ceshi123 Nov 20, 2020 3631 views
    This topic created in 1987 days ago, the information mentioned may be changed or developed.

    AQS 中获取公平锁的代码如下( jdk1.8 ): protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } }

    如果有三个线程来获取公平锁,第一个线程获取成功,第二与第三个线程走到 hasQueuedPredecessors(),都判断出为 false(此时队列为空,他们都可以获取锁),第二个线程继续走(第三个线程时间片到了,停住),获取锁失败(因为锁已经被第一个线程获取了),那就乖乖的去排队,构造头结点与自己的节点,此时 sync 队列为: head → node2,node2 → head,然后第二个线程又来抢占锁(源码中有个 for 循环),走到 hasQueuedPredecessors(),判断出也为 false (因为自己就是队列中的第二个节点,是有资格抢锁的),此时线程一释放了锁,那么第二个线程与第三个线程同时抢锁,锁是有可能被三个线程抢到了。

    那么这是不是违背了公平锁的概念,或者公平锁并不是绝对的公平,因为第二个线程已经在队列里面排好了队,也该是自己拿到锁,结果锁被第三个线程拿走了。

    麻烦各位大神解惑一下!!!

    8 replies    2020-11-20 14:38:26 +08:00
    ceshi123
        1
    ceshi123  
    OP
       Nov 20, 2020
    我擦,大神呢
    yamasa
        2
    yamasa  
       Nov 20, 2020
    我觉得 tryAccquire 的这一段注释可以解答这个问题了:

    Likewise, it is possible for another thread to win a race to enqueue after this method has returned {@code false}, due to the queue being empty.
    ceshi123
        3
    ceshi123  
    OP
       Nov 20, 2020
    @yamasa 那其实它在极端场景下是并不是完全公平的
    yamasa
        4
    yamasa  
       Nov 20, 2020
    @ceshi123 对 而且可以说对于绝大部分场景,非公平的 performance 都更好
    THESDZ
        5
    THESDZ  
       Nov 20, 2020
    大部分的程序只会考虑绝大多数的情况,因为要考虑所有情况或者极端情况的话,成本>>收益
    THESDZ
        6
    THESDZ  
       Nov 20, 2020
    @THESDZ #5 如果的确要考虑极端情况,通常情况是通过"事后"补救
    1194129822
        7
    1194129822  
       Nov 20, 2020
    你这理解不对,首先说一下,公平只是相对的公平,所有公平模式,就是如果前面有线程排队就加入队尾,而非公平模式,就是线程直接尝试获取锁,获取失败才排队。但是线程本身的执行是没有顺序和优先级的。如果线程 2 因为 os 调度,一直得不到运行,可能一直永远排队。
    wysnylc
        8
    wysnylc  
       Nov 20, 2020
    公平是相对的而且不同的角度也会有不同见解
    无序的争抢才是高效
    About     Help     Advertise     Blog     API     FAQ     Solana     5565 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 40ms UTC 06:36 PVG 14:36 LAX 23:36 JFK 02:36
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86