是否有可能与两个线程 lockRoot 的 ConcurrentHashMap 发生死锁

Is it possible to get a deadlock with ConcurrentHashMap with two threads lockRoot

如果两个线程同时将 vals 放入一棵树中

private final void contendedLock() {
        boolean waiting = false;
        for (int s;;) {
            if (((s = lockState) & ~WAITER) == 0) {
                if (U.compareAndSwapInt(this, LOCKSTATE, s, WRITER)) {
                    if (waiting)
                        waiter = null;
                    return;
                }
            }
            else if ((s & WAITER) == 0) {
                if (U.compareAndSwapInt(this, LOCKSTATE, s, s | WAITER)) {
                    waiting = true;
                    waiter = Thread.currentThread();
                }
            }
            else if (waiting)
                LockSupport.park(this);
        }
    }

Thread1:CAS 锁定状态到 WRITER

Thread2:CAS 锁定状态到 (WRITER|WAITER)

线程 2:LockSupport.park(这个)

线程 1:unlockRoot

private final void unlockRoot() {
        lockState = 0;
    }

那谁能解开 Thread2?

find() 方法的最后一部分需要在严格的条件下完成

finally {
                        Thread w;
                        if (U.getAndAddInt(this, LOCKSTATE, -READER) ==
                            (READER|WAITER) && (w = waiter) != null)
                            LockSupport.unpark(w);
                    }

谁能告诉我我是不是想错了?

您的推理是基于这样的假设,即 2 个写入线程可能会进入 contendedLock() 方法,而第二个写入线程将自行无限期停放,这当然是不可能的,因为 putVal 是相关树的 synchronized on the root node

事实上,lockState 仅用于通过 CAS 编排 readers 与 writers,并且仅当 reader 和 writer 都尝试访问相同的 RB 树(即他们都对具有相同散列的密钥进行操作)。

在这种情况下,一旦发现 lockState=READER,编写器线程就会自行停止(然后通过 OR (s | WAITER) 将 WAITER 位添加到 lockState 中. 这个值 (00000110) 稍后将被 reader 在 finally 块中使用以取消停放写入线程(一旦它通过添加 -READER 清除读取状态,即 -4 , 并且看到之前的值也是 00000110)