ConcurrentHashMap 源码分析01之类定义、属性、内部类

都知道 HashMap 是线程不安全的。那应该怎么解决呢?除了 Collections 工具类实现(底层重要方法加上Synchronize关键字),就是本文的ConcurrentHashMap,采用了粒度更小的片段加锁方式。

1. 类的定义

  • 虽然名字中也有 HashMap,但是并没有继承 HashMap。
  • ConcurrentHashMap 继承 AbstractMap,实现 ConcurrentMap、Serializable,即表示是一个可序列化的 Map
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
    implements ConcurrentMap<K,V>, Serializable {}

1.1 先来看 ConcurrentHashMap 的构造函数

  • ConcurrentHashMap 总共有 5 个构造函数
/* 空构造函数:使用默认容量为 16 */
public ConcurrentHashMap() {
}
/* initialCapacity:初始容量 */
public ConcurrentHashMap(int initialCapacity) {
	/* 初始容量不能小于 0 */
    if (initialCapacity < 0)
        throw new IllegalArgumentException();
    /* 若指定的初始容量 >= 最大容量的一半,使用最大容量MAXIMUM_CAPACITY
     * 否则获取最靠近 (1.5倍初始容量 + 1)的 2的指数次幂的整数 */
    /* 这里的1.5倍,我的理解是这样:若传入的初始容量为12,扩容因子为0.75
     * 若只用 12 传入,则 cap 应为 16,一般情况下,我们初始一个容量,都会加入对应的元素,则元素个数到达12时会进行扩容
     * 若使用 12 * 1.5 + 1 = 19,则 cap 应为 32,元素个数到达12时,不会进行扩容
     * 至于为什么 HashMap 不这样使用,我也不知道  */     
    int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
               MAXIMUM_CAPACITY :
               tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
    /* 设置 sizeCtl 为计算后的初始容量cap */
    this.sizeCtl = cap;
}
/* 指定初始容量,扩容因子,初始化并发数为 1 */
public ConcurrentHashMap(int initialCapacity, float loadFactor) {
    this(initialCapacity, loadFactor, 1);
}
/* concurrencyLevel: 并发数量,jdk1.8 有多少个桶就有多少个并发数 */
public ConcurrentHashMap(int initialCapacity,
                         float loadFactor, int concurrencyLevel) {
    /* 加载因子 < 0 || 初始容量 < 0 || concurrencyLevel < = 0 则报参数错误 */                     
    if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
        throw new IllegalArgumentException();
    /* 容量应该大于并发线程数,不然没有意义 */    
    if (initialCapacity < concurrencyLevel)
        initialCapacity = concurrencyLevel;
    /* 使用传入的初始容量initialCapacity /扩容因子loadFactor + 1 计算大致的元素个数 */    
    long size = (long)(1.0 + (long)initialCapacity / loadFactor);
    /* 元素个数 >= 最大容量,则使用最大容量值,否则使用最接近 size 的 2 的指数次幂  */
    int cap = (size >= (long)MAXIMUM_CAPACITY) ?
        MAXIMUM_CAPACITY : tableSizeFor((int)size);
    this.sizeCtl = cap;
}
/* 初始化集合 map */
public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
	/* 使用默认容量 */
    this.sizeCtl = DEFAULT_CAPACITY;
    /* 添加集合m 的作用元素,后面详讲 */
    putAll(m);
}
  • 小总结:对比HashMap,ConcurrentHashMap 构造函数中多了一个属性 sizeCtl,有什么作用呢? 接着往下看。

1.2 ConcurrentHashMap 的属性

  • static 变量
/* 万年不变的版本号 */
private static final long serialVersionUID = 7249069246763182397L;
/* 数组最大容量 */
private static final int MAXIMUM_CAPACITY = 1 << 30;
/* 默认初始容量,必须为2 的指数次幂,不超过最大容量 1 << 30 */
private static final int DEFAULT_CAPACITY = 16;
/* 最大数组长度 */
static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/* 默认并发数 */
private static final int DEFAULT_CONCURRENCY_LEVEL = 16;
/* 默认扩容因子 */
private static final float LOAD_FACTOR = 0.75f;
/* 默认树化元素个数 */
static final int TREEIFY_THRESHOLD = 8;
/* 退化成链元素个数 */
static final int UNTREEIFY_THRESHOLD = 6;
/* 最小树化容量 */
static final int MIN_TREEIFY_CAPACITY = 64;
/* 扩容时数据前移的步长,默认最小为16 */
private static final int MIN_TRANSFER_STRIDE = 16;
/* 扩容位数标识,主要用于扩容时生成一个巨大负数使用(细品第32位的标志位与 16位为1左移16位) */
private static int RESIZE_STAMP_BITS = 16;
/* 最大并发线程数 65535 */
private static final int MAX_RESIZERS = (1 << (32 - RESIZE_STAMP_BITS)) - 1;
/* 扩容位数标识剩下的位数 */
private static final int RESIZE_STAMP_SHIFT = 32 - RESIZE_STAMP_BITS;
/* 节点标识 */
static final int MOVED     = -1; // 节点正在扩容
static final int TREEBIN   = -2; // 树节点
static final int RESERVED  = -3; // 正在设置桶位首节点,与只有一个节点区分
static final int HASH_BITS = 0x7fffffff; // usable bits of normal node hash
/* 系统CPu数量 */
static final int NCPU = Runtime.getRuntime().availableProcessors();
/* 用于序列化兼容性 */
private static final ObjectStreamField[] serialPersistentFields = {
    new ObjectStreamField("segments", Segment[].class),
    new ObjectStreamField("segmentMask", Integer.TYPE),
    new ObjectStreamField("segmentShift", Integer.TYPE)
};

// Unsafe mechanics
private static final sun.misc.Unsafe U;
private static final long SIZECTL;
private static final long TRANSFERINDEX;
private static final long BASECOUNT;
private static final long CELLSBUSY;
private static final long CELLVALUE;
private static final long ABASE;
private static final int ASHIFT;
static {
    try {
        U = sun.misc.Unsafe.getUnsafe();
        Class<?> k = ConcurrentHashMap.class;
        SIZECTL = U.objectFieldOffset
            (k.getDeclaredField("sizeCtl"));
        TRANSFERINDEX = U.objectFieldOffset
            (k.getDeclaredField("transferIndex"));
        BASECOUNT = U.objectFieldOffset
            (k.getDeclaredField("baseCount"));
        CELLSBUSY = U.objectFieldOffset
            (k.getDeclaredField("cellsBusy"));
        Class<?> ck = CounterCell.class;
        CELLVALUE = U.objectFieldOffset
            (ck.getDeclaredField("value"));
        Class<?> ak = Node[].class;
        ABASE = U.arrayBaseOffset(ak);
        int scale = U.arrayIndexScale(ak);
        if ((scale & (scale - 1)) != 0)
            throw new Error("data type scale not a power of two");
        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
    } catch (Exception e) {
        throw new Error(e);
    }
}
  • 实例变量
/* 存储数据的底层数组 */
transient volatile Node<K,V>[] table;
/* 扩容用的新数组,扩容完成后置为null,默认为null */
private transient volatile Node<K,V>[] nextTable;
/* 元素个数的基础计数,加上counterCells数组所有元素的value值总和 即为所有元素个数 */
private transient volatile long baseCount;
/* 扩容指数:为0 是默认值,为负数则正在扩容,为正数代表临界值(阈值) */
private transient volatile int sizeCtl;

/* 标识扩容时还未被分配迁移数据的个数 */
private transient volatile int transferIndex;

/* 用于判断counterCells是否正在被使用,0为可使用,1为当前有线程正在使用 */
private transient volatile int cellsBusy;

/* 并发情况下,使用该数组进行count联合计数,减少baseCount的计数压力,提高效率 */
private transient volatile CounterCell[] counterCells;

/* key,value,entry 集合 */
private transient KeySetView<K,V> keySet;
private transient ValuesView<K,V> values;
private transient EntrySetView<K,V> entrySet;
  • 总结:相比 HashMap,ConcurrentHashMap 具有更多的属性,看着也迷迷糊糊。先了解大概印象,等摸清全部脉络,再来回顾。

1.3 内部类

  • ConcurrentHashMap 有几十个内部类,慢慢来,总会搞明白的。

1.3.1 Node

  • 与 HashMap 的不同,就是 val 与 next 增加了 volatile 修饰符,修改具有可见性。
  • 有ForwardingNode、ReservationNode、TreeNode和TreeBin四个子类。
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    volatile V val;
    volatile Node<K,V> next;
	/* 全参构造函数 */
    Node(int hash, K key, V val, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.val = val;
        this.next = next;
    }

    public final K getKey() { return key; }
    public final V getValue() { return val; }
    /* 重写 hashCode */
    public final int hashCode() { return key.hashCode() ^ val.hashCode(); }
    public final String toString(){ return key + "=" + val; }
    /* 不能修改 value 值,否则报错 UnsupportedOperationException */
    public final V setValue(V value) {
        throw new UnsupportedOperationException();
    }
	/* 相同节点判断 */
    public final boolean equals(Object o) {
        Object k, v, u; Map.Entry<?,?> e;
        /* 是否属于Map.Entry 的实例
         * key 值是否为空, value 值是否为空
         * key 值是否相等, value 值是否相等
         * */
        return ((o instanceof Map.Entry) &&
                (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
                (v = e.getValue()) != null &&
                (k == key || k.equals(key)) &&
                (v == (u = val) || v.equals(u)));
    }

    /* 查找 k 对应的节点 */
    Node<K,V> find(int h, Object k) {
    	/* 从当前节点e 开始遍历,找到返回节点e,找不到返回 null */
        Node<K,V> e = this;
        if (k != null) {
            do {
                K ek;
                if (e.hash == h &&
                    ((ek = e.key) == k || (ek != null && k.equals(ek))))
                    return e;
            } while ((e = e.next) != null);
        }
        return null;
    }
}

1.3.2 Segment<K,V>

  • Segment 继承了 ReentrantLock,即具有lock的所有特性,只有一个构造函数,指定扩容因子
static class Segment<K,V> extends ReentrantLock implements Serializable {
    private static final long serialVersionUID = 2249069246763182397L;
    final float loadFactor;
    Segment(float lf) { this.loadFactor = lf; }
}

1.3.3 ForwardingNode

  • ForwardingNode 继承 Node,扩容时使用,标志当前节点正在移位
static final class ForwardingNode<K,V> extends Node<K,V> {
    final Node<K,V>[] nextTable;
    /* 指定 MOVED 为当前节点的 Hash,标志正在移位 */
    ForwardingNode(Node<K,V>[] tab) {
        super(MOVED, null, null, null);
        this.nextTable = tab;
    }
	/* 查找 k 节点 */
    Node<K,V> find(int h, Object k) {
        // loop to avoid arbitrarily deep recursion on forwarding nodes
        outer: for (Node<K,V>[] tab = nextTable;;) {
            Node<K,V> e; int n;
            /* 找不到对应的节点,返回 null */
            if (k == null || tab == null || (n = tab.length) == 0 ||
                (e = tabAt(tab, (n - 1) & h)) == null) // 已经进行 e 的赋值
                return null;
            for (;;) {
                int eh; K ek;
                /* 找到对应的节点,直接返回 */
                if ((eh = e.hash) == h &&
                    ((ek = e.key) == k || (ek != null && k.equals(ek))))
                    return e;
                /* e.hash < 0  */    
                if (eh < 0) {
                	/* 判断当前节点是否为 ForwardingNode */
                    if (e instanceof ForwardingNode) {
                        tab = ((ForwardingNode<K,V>)e).nextTable;
                        continue outer;
                    }
                    else
                        return e.find(h, k);
                }
                if ((e = e.next) == null)
                    return null;
            }
        }
    }
}

1.3.4 ReservationNode

  • 用于CAS设置桶位首节点时使用,抢到权限后首节点会设置成Node,即ReservationNode 只有过渡作用
static final class ReservationNode<K,V> extends Node<K,V> {
    ReservationNode() {
        super(RESERVED, null, null, null);
    }
	/* 直接返回 null,无节点可查找 */
    Node<K,V> find(int h, Object k) {
        return null;
    }
}

1.3.5 CounterCell

  • 主要用于对baseCount的计数
@sun.misc.Contended static final class CounterCell {
    volatile long value;
    CounterCell(long x) { value = x; }
}

1.3.6 TreeNode<K,V>

  • 树节点,继承 Node,
static final class TreeNode<K,V> extends Node<K,V> {
    TreeNode<K,V> parent;  // 父节点
    TreeNode<K,V> left;	   // 左节点	
    TreeNode<K,V> right;   // 右节点	
    TreeNode<K,V> prev;    // 前置节点
    boolean red;	// 节点颜色
	/* 构造函数:指定属性 */
    TreeNode(int hash, K key, V val, Node<K,V> next,
             TreeNode<K,V> parent) {
        super(hash, key, val, next);
        this.parent = parent;
    }
	/* 查找节点,底层调用 findTreeNode */
    Node<K,V> find(int h, Object k) {
        return findTreeNode(h, k, null);
    }

    /* 查找树节点 */
    final TreeNode<K,V> findTreeNode(int h, Object k, Class<?> kc) {
        /* key 为 null 直接返回 null */
        if (k != null) {
        	/* 设置 p 为当前节点 */
            TreeNode<K,V> p = this;
            do  {
            	/* ph: p.hash, pk: p.key, q: 中转节点 */
                int ph, dir; K pk; TreeNode<K,V> q;
                /* 获取左右节点 */
                TreeNode<K,V> pl = p.left, pr = p.right;
                if ((ph = p.hash) > h)
                    p = pl; // 往左找
                else if (ph < h)
                    p = pr; // 往右找
                /* hash 相等,判断 key 是否相等 */     
                else if ((pk = p.key) == k || (pk != null && k.equals(pk)))
                    return p;
                /* hash 相等,key 不相等 */    
                else if (pl == null)
                    p = pr; // 左节点为空,往右找
                else if (pr == null)
                    p = pl; // 右节点为空,往左找
                /* 左右不为空,使用 comparableClass 比较出大小*/    
                else if ((kc != null ||
                          (kc = comparableClassFor(k)) != null) &&
                         (dir = compareComparables(kc, k, pk)) != 0)
                    p = (dir < 0) ? pl : pr;
                /* 实在比较不出,先往右节点递归 */    
                else if ((q = pr.findTreeNode(h, k, kc)) != null)
                    return q;
                else
                    p = pl; // 右节点找不到往左
            } while (p != null);
        }
        return null;
    }
}

1.3.7 TreeBin<K,V>

static final class TreeBin<K,V> extends Node<K,V> {
    TreeNode<K,V> root; // root 节点
    volatile TreeNode<K,V> first; // 首节点
    volatile Thread waiter; // 等待线程
    volatile int lockState; // 锁状态
    // values for lockState
    static final int WRITER = 1; // 持有写锁
    static final int WAITER = 2; // 等待写锁
    static final int READER = 4; // 读锁

    /* 用于hash值相等,但使用 compareComparables 也比较不出 key 大小的情况  */
    static int tieBreakOrder(Object a, Object b) {
        int d;
        /* 若 className 比较不出大小,则使用 identityHashCode */
        if (a == null || b == null ||
            (d = a.getClass().getName().
             compareTo(b.getClass().getName())) == 0)
            d = (System.identityHashCode(a) <= System.identityHashCode(b) ?
                 -1 : 1);
        return d;
    }

    /* 构造函数:传入一个 树节点TreeNode */
    TreeBin(TreeNode<K,V> b) {
        super(TREEBIN, null, null, null); // Node 构造函数
        this.first = b; // 设置 b 为首节点
        TreeNode<K,V> r = null; // 初始化根节点
        for (TreeNode<K,V> x = b, next; x != null; x = next) {
            next = (TreeNode<K,V>)x.next; // 获取 next 节点
            x.left = x.right = null;
            /* 初始化根节点 */
            if (r == null) {
                x.parent = null;
                x.red = false;
                r = x;
            }
            else {
                K k = x.key;
                int h = x.hash;
                Class<?> kc = null;
                /* p 为 x 的父节点 */
                for (TreeNode<K,V> p = r;;) {
                    int dir, ph;
                    K pk = p.key;
                    /* 判断节点 x 应该存放的位置 */
                    if ((ph = p.hash) > h)
                        dir = -1;
                    else if (ph < h)
                        dir = 1;
                    else if ((kc == null &&
                              (kc = comparableClassFor(k)) == null) ||
                             (dir = compareComparables(kc, k, pk)) == 0)
                        dir = tieBreakOrder(k, pk);
                        TreeNode<K,V> xp = p;
                    /* 根据 dir 判断 x 为 p 的左节点还是右节点 */    
                    if ((p = (dir <= 0) ? p.left : p.right) == null) {
                        x.parent = xp;
                        if (dir <= 0)
                            xp.left = x;
                        else
                            xp.right = x;
                        /* 插入平衡操作 */    
                        r = balanceInsertion(r, x);
                        break;
                    }
                }
            }
        }
        this.root = r; // 设置 根节点
        assert checkInvariants(root);
    }

    /* 根节点的加锁,锁的是当前桶位 */
    private final void lockRoot() {
        if (!U.compareAndSwapInt(this, LOCKSTATE, 0, WRITER))
            contendedLock(); // CAS失败
    }

    /* 根节点解锁 */
    private final void unlockRoot() {
        lockState = 0;
    }

    /* 阻塞等待 root 锁 */
    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;
                }
            }
            /* 有线程持有写锁且本线程状态不为WAITER时 */
            else if ((s & WAITER) == 0) {
            	/* 尝试占有waiting线程 */
                if (U.compareAndSwapInt(this, LOCKSTATE, s, s | WAITER)) {
                    waiting = true;
                    waiter = Thread.currentThread();
                }
            }
            /* 有线程持有写锁且本线程状态为WAITER时,堵塞自己 */
            else if (waiting)
                LockSupport.park(this);
        }
    }

    /* 寻找节点的方法 */
    final Node<K,V> find(int h, Object k) {
    	/* key 为null, 直接返回null */
        if (k != null) {
        	/* 首节点开始比较 */
            for (Node<K,V> e = first; e != null; ) {
                int s; K ek;
                /* 写锁被持有时使用链表的方法遍历 */
                if (((s = lockState) & (WAITER|WRITER)) != 0) {
                	/* 比较key 是否相等 */
                    if (e.hash == h &&
                        ((ek = e.key) == k || (ek != null && k.equals(ek))))
                        return e;
                    e = e.next;
                }
                /* 写锁没被持有时,持有一个读锁,用红黑树的方法遍历 */
                else if (U.compareAndSwapInt(this, LOCKSTATE, s,
                                             s + READER)) {
                    TreeNode<K,V> r, p;
                    try {
                        p = ((r = root) == null ? null :
                             r.findTreeNode(h, k, null));
                    } finally {
                        Thread w;
                        /* 当前线程持有最后一个读锁的时候通知waiter线程获取写锁 */
                        /* 为什么剩下一个读锁时唤醒等待线程,我也不知道 */
                        if (U.getAndAddInt(this, LOCKSTATE, -READER) ==
                            (READER|WAITER) && (w = waiter) != null)
                            LockSupport.unpark(w);
                    }
                    return p;
                }
            }
        }
        return null;
    }

    /* 添加节点 */
    final TreeNode<K,V> putTreeVal(int h, K k, V v) {
        Class<?> kc = null;
        boolean searched = false;
        for (TreeNode<K,V> p = root;;) {
            int dir, ph; K pk;
            /* root 为空,直接添加 */
            if (p == null) {
                first = root = new TreeNode<K,V>(h, k, v, null, null);
                break;
            }
            /* 判断 p 节点插入的位置 */
            else if ((ph = p.hash) > h)
                dir = -1;
            else if (ph < h)
                dir = 1;
            /* key 相等则返回 p */    
            else if ((pk = p.key) == k || (pk != null && k.equals(pk)))
                return p;
            /* hash相等,key不相等  */    
            else if ((kc == null &&
                      (kc = comparableClassFor(k)) == null) ||
                     (dir = compareComparables(kc, k, pk)) == 0) {
                /* searched 表示为true遍历过所有元素且没有与k相等的key  */     
                if (!searched) {
                    TreeNode<K,V> q, ch;
                    searched = true;
                    /* 先往左递归,再往右递归 */
                    if (((ch = p.left) != null &&
                         (q = ch.findTreeNode(h, k, kc)) != null) ||
                        ((ch = p.right) != null &&
                         (q = ch.findTreeNode(h, k, kc)) != null))
                        return q;
                }
                dir = tieBreakOrder(k, pk); // comparableClass 比较不出key大小时执行
            }
			
            TreeNode<K,V> xp = p;
            /* 根据 dir 判断左右节点,若对应的子节点为null,则已找到插入位置,否则继续循环 */
            if ((p = (dir <= 0) ? p.left : p.right) == null) {
                TreeNode<K,V> x, f = first;
                /* 将插入的节点设置为 first 节点 */
                first = x = new TreeNode<K,V>(h, k, v, f, xp);
                if (f != null)
                    f.prev = x;
                /* 根据dir 判断左右节点*/    
                if (dir <= 0)
                    xp.left = x;
                else
                    xp.right = x;
                /* 父节点为黑色,直接插入 */
                if (!xp.red)
                    x.red = true;
                else {
                	/* 锁住根节点,进行红黑树插入平衡 */
                    lockRoot();
                    try {
                        root = balanceInsertion(root, x);
                    } finally {
                        unlockRoot();
                    }
                }
                break;
            }
        }
        assert checkInvariants(root);
        return null;
    }

    /* 删除 removeTreeNode 节点 */
    final boolean removeTreeNode(TreeNode<K,V> p) {
        TreeNode<K,V> next = (TreeNode<K,V>)p.next; // 后继节点
        TreeNode<K,V> pred = p.prev;  // 前置节点
        TreeNode<K,V> r, rl;
        /* 处理链表的节点指针,删除 p */
        if (pred == null)
            first = next;
        else
            pred.next = next;
        if (next != null)
            next.prev = pred;
        /* 没有节点了,直接返回 */    
        if (first == null) {
            root = null;
            return true;
        }
        /* 个数太少:root 为空 || root.right 为空 || root.left为空 || root.left.left 为空 */
        if ((r = root) == null || r.right == null || // too small
            (rl = r.left) == null || rl.left == null)
            return true;
        /* 锁住根节点 */    
        lockRoot();
        try {
            TreeNode<K,V> replacement; // 替代节点
            TreeNode<K,V> pl = p.left; // p 的左节点
            TreeNode<K,V> pr = p.right; // p 的右节点
            /* 左右节点都不为空 */
            if (pl != null && pr != null) {
                TreeNode<K,V> s = pr, sl; // s 为 p.right
                while ((sl = s.left) != null) // 获得后继节点,右子树的最左子节点
                    s = sl;
                /* 交换 后继节点s 与 删除节点p 的颜色 */    
                boolean c = s.red; s.red = p.red; p.red = c;
                TreeNode<K,V> sr = s.right;
                TreeNode<K,V> pp = p.parent;
                /* 可自行画图,交换 s,p 节点需要更换哪些指针,对照代码看更清楚(parent,left,right) */
                /* p.right 为后继节点,即 p.right 没有左子节点 */
                if (s == pr) {
                	/* 交换 s,p 的指针 */
                    p.parent = s;
                    s.right = p;
                }
                else {
                	/* 交换 s,p 的指针 */
                    TreeNode<K,V> sp = s.parent;
                    if ((p.parent = sp) != null) {
                        if (s == sp.left)
                            sp.left = p;
                        else
                            sp.right = p;
                    }
                    if ((s.right = pr) != null)
                        pr.parent = s;
                }
                p.left = null; // s没有左子节点
                if ((p.right = sr) != null)
                    sr.parent = p;
                if ((s.left = pl) != null)
                    pl.parent = s;
                if ((s.parent = pp) == null)
                    r = s;
                else if (p == pp.left)
                    pp.left = s;
                else
                    pp.right = s;
                /* 若右节点存在,由于删除的是替代节点,变成只有右子节点的情况 */    
                if (sr != null)
                    replacement = sr;
                else
                    replacement = p;
            }
            else if (pl != null)
                replacement = pl;  // 只有左子节点
            else if (pr != null)
                replacement = pr;  // 只有右子节点
            else
                replacement = p;  // 没有子节点,亲自上阵
            /* 若具有替代节点,先删除节点p */
            if (replacement != p) {
                TreeNode<K,V> pp = replacement.parent = p.parent;
                if (pp == null)
                    r = replacement;
                else if (p == pp.left)
                    pp.left = replacement;
                else
                    pp.right = replacement;
                p.left = p.right = p.parent = null;
            }
			/* 若删除的不是红色节点,需要进行红黑树删除平衡操作 */
            root = (p.red) ? r : balanceDeletion(r, replacement);
			/* 由于平衡操作不会删除节点,亲自上的情况需要平衡后进行节点删除 */
            if (p == replacement) {
                TreeNode<K,V> pp;
                if ((pp = p.parent) != null) {
                    if (p == pp.left)
                        pp.left = null;
                    else if (p == pp.right)
                        pp.right = null;
                    p.parent = null;
                }
            }
        } finally {
            unlockRoot();
        }
        /* 检测红黑树状态 */
        assert checkInvariants(root);
        return false;
    }

    /* ---------------红黑树平衡操作-------------- */

	/* root: 根节点 , x: 新插入的节点 */
	static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,
	                                                TreeNode<K,V> x) {
	    /* 插入的节点都为红色节点,不然就没有红黑树了 */
	    x.red = true;
	    /* xp: x 的父亲节点, xpp: x 的爷爷节点, xppl: x 的爷爷节点的左节点, xppr: x 的爷爷节点的右节点 */
	    for (TreeNode<K,V> xp, xpp, xppl, xppr;;) {
	    	/* 情景1:红黑树为空树,设置 x 节点为根节点,改为黑色 */
	        if ((xp = x.parent) == null) {
	            x.red = false;
	            return x;
	        }
	        /* 情景3:父节点为黑色,直接赋值,不用操作 || 爷爷节点为空(其实就是父节点为 root , 就是为了赋值) */
	        else if (!xp.red || (xpp = xp.parent) == null)
	            return root;
	            
	        /* 情景4.2:父节点为祖父节点的左节点 */
	        if (xp == (xppl = xpp.left)) {
	        	/* 情景4.1:叔叔节点(右节点)不为空且为红色节点 */
	            if ((xppr = xpp.right) != null && xppr.red) {
	            	/* 叔叔节点、父亲节点设置为黑色,爷爷节点设置为红色,x 设置为爷爷节点,上层传递 */
	                xppr.red = false;
	                xp.red = false;
	                xpp.red = true;
	                x = xpp;
	            }
	            else {
	            	/* 情景4.2.2 插入节点是其父节点的右子节点 */
	                if (x == xp.right) {
	                    root = rotateLeft(root, x = xp);
	                    xpp = (xp = x.parent) == null ? null : xp.parent;
	                }
	                /* 情景4.2.1 插入节点是其父节点的左子节点 */
	                if (xp != null) {
	                    xp.red = false;
	                    if (xpp != null) {
	                        xpp.red = true;
	                        root = rotateRight(root, xpp);
	                    }
	                }
	            }
	        }
	        /* 情景4.3:父节点为祖父节点的右节点 */
	        else {
	        	/* 情景4.1:叔叔节点(右节点)不为空且为红色节点 */
	            if (xppl != null && xppl.red) {
	            	/* 父亲节点、叔叔节点变为黑色,爷爷节点变为红色,x = xpp 将红色节点向上抛 */
	                xppl.red = false;
	                xp.red = false;
	                xpp.red = true;
	                x = xpp;
	            }
	            else {
	            	/* 情景4.3.2 插入节点是其父节点的左子节点 */
	                if (x == xp.left) {
	                    root = rotateRight(root, x = xp);
	                    xpp = (xp = x.parent) == null ? null : xp.parent;
	                }
	                /* 情景4.3.1 插入节点是其父节点的右子节点 */
	                if (xp != null) {
	                	/* 父节点设置为黑色 */
	                    xp.red = false;
	                    if (xpp != null) {
	                    	/* 爷爷节点设置为红色,并进行左旋 */
	                        xpp.red = true;
	                        root = rotateLeft(root, xpp);
	                    }
	                }
	            }
	        }
	    }
	}

	/* root: 根节点, x:删除的节点 */
	static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
	                                           TreeNode<K,V> x) {
	    
	    for (TreeNode<K,V> xp, xpl, xpr;;) {
	    	/* x 为null || x 为根节点时退出 */
	        if (x == null || x == root)
	            return root;
	        /* 删除情况2,只有一个子节点且删除的节点为 root */  
	        /* 出现的情况是 root 有一个子结点,删除root */  
	        else if ((xp = x.parent) == null) {
	            x.red = false;
	            return x;
	        }
	        /* 情景1:节点为红色直接删除 */
	        else if (x.red) {
	            x.red = false;
	            return root;
	        }
	        /* 情景2.1:替换节点是左节点 */
	        else if ((xpl = xp.left) == x) {
	        	/* 情景2.1.1:替换节点的兄弟节点为红色 */
	            if ((xpr = xp.right) != null && xpr.red) {
	                xpr.red = false;
	                xp.red = true;
	                root = rotateLeft(root, xp);
	                xpr = (xp = x.parent) == null ? null : xp.right;
	            }
	            /* 情景2.1.2.3: 替换结点的兄弟结点的子结点都为黑结点,兄弟节点为null,无需变红
	            可以看作是排除没有子节点的情况 */
	            if (xpr == null)
	                x = xp;
	            else {
	                TreeNode<K,V> sl = xpr.left, sr = xpr.right;
	                /* 情景2.1.2.3: 替换结点的兄弟结点的子结点都为黑结点 */
	                if ((sr == null || !sr.red) &&
	                    (sl == null || !sl.red)) {
	                    xpr.red = true;
	                    x = xp;
	                }
	                else {
	                	/* 情景2.1.2.2: 替换结点的兄弟结点的右子结点是黑结点,左子结点为红色节点 */
	                    if (sr == null || !sr.red) {
	                        if (sl != null)
	                            sl.red = false;
	                        xpr.red = true;
	                        root = rotateRight(root, xpr);
	                        /* 旋转后更换兄弟节点 */
	                        xpr = (xp = x.parent) == null ?
	                            null : xp.right;
	                    }
	                    /* 情景2.1.2.1: 替换结点的兄弟结点的右子结点是红结点,左子结点任意颜色 */
	                    if (xpr != null) {
	                        xpr.red = (xp == null) ? false : xp.red;
	                        if ((sr = xpr.right) != null)
	                            sr.red = false;
	                    }
	                    if (xp != null) {
	                        xp.red = false;
	                        root = rotateLeft(root, xp);
	                    }
	                    /* 到这里,删除平衡操作已完成,将 x == root 为了下一次进入循环直接退出,我也不知道为什么不直接 return root */
	                    x = root;
	                }
	            }
	        }
	        /* 情景2.2:替换节点是右节点 */
	        else {
	        	/* 情景2.2.1: 替换结点的兄弟结点是红结点 */
	            if (xpl != null && xpl.red) {
	                xpl.red = false;
	                xp.red = true;
	                root = rotateRight(root, xp);
	                xpl = (xp = x.parent) == null ? null : xp.left;
	            }
	            /* 情景2.2.2.3: 替换结点的兄弟结点的子结点都为黑结点(NIL),兄弟节点为null,无需变红
	            可以看作是排除没有子节点的情况 */
	            if (xpl == null)
	                x = xp;
	            else {
	            	/* 情景2.2.2.3: 替换结点的兄弟结点的子结点都为黑结点 */
	                TreeNode<K,V> sl = xpl.left, sr = xpl.right;
	                if ((sl == null || !sl.red) &&
	                    (sr == null || !sr.red)) {
	                    xpl.red = true;
	                    x = xp;
	                }
	                else {
	                	/* 情景2.2.2.2: 替换结点的兄弟结点的左子结点是黑结点,右子结点为红色节点 */
	                    if (sl == null || !sl.red) {
	                        if (sr != null)
	                            sr.red = false;
	                        xpl.red = true;
	                        root = rotateLeft(root, xpl);
	                        /* 旋转后更换兄弟节点 */
	                        xpl = (xp = x.parent) == null ?
	                            null : xp.left;
	                    }
	                    /* 情景2.2.2.1: 替换结点的兄弟结点的左子结点是红结点,右子结点任意颜色 */
	                    if (xpl != null) {
	                        xpl.red = (xp == null) ? false : xp.red;
	                        if ((sl = xpl.left) != null)
	                            sl.red = false;
	                    }
	                    if (xp != null) {
	                        xp.red = false;
	                        root = rotateRight(root, xp);
	                    }
	                    /* 到这里,删除平衡操作已完成,将 x == root 为了下一次进入循环直接退出,我也不知道为什么不直接 return root */
	                    x = root;
	                }
	            }
	        }
	    }
	}

    /* t: 传入的某个节点 */
	static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
		/* tp: 根节点的父节点,tl: 根节点的左节点, tr: 根节点的右节点 */
	    TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,
	    	/* tb: 根节点的前置节点,tn: 根节点后置节点 */
	        tb = t.prev, tn = (TreeNode<K,V>)t.next;
	    /* 出现以下任何一种情况,则表示树结构或者链结构不正确 */   
	    /* 1. 前驱节点存在,但是前驱节点的后置节点不为 t */ 
	    if (tb != null && tb.next != t)
	        return false;
	    /* 2. 后置节点存在,但是后置节点的前驱节点不为 t */    
	    if (tn != null && tn.prev != t)
	        return false;
	    /* 父节点存在,但是 t 不是父节点的左子节点 or 右子节点 */    
	    if (tp != null && t != tp.left && t != tp.right)
	        return false;
	    /* 左节点存在,但左节点的父节点不是 t || 左节点的hash值 > t的hash值 */    
	    if (tl != null && (tl.parent != t || tl.hash > t.hash))
	        return false;
	    /* 右节点存在,但右节点的父节点不是 t || 右节点的hash值 < t的hash值 */     
	    if (tr != null && (tr.parent != t || tr.hash < t.hash))
	        return false;
	    /* 当前节点为红色 且 子节点也为红色 */    
	    if (t.red && tl != null && tl.red && tr != null && tr.red)
	        return false;
	    /* 递归验证左子树 */    
	    if (tl != null && !checkInvariants(tl))
	        return false;
	    /* 递归验证右子树 */    
	    if (tr != null && !checkInvariants(tr))
	        return false;
	    /* 都正确返回 true */    
	    return true;
	}

    private static final sun.misc.Unsafe U;
    private static final long LOCKSTATE;
    static {
        try {
            U = sun.misc.Unsafe.getUnsafe();
            Class<?> k = TreeBin.class;
            LOCKSTATE = U.objectFieldOffset
                (k.getDeclaredField("lockState"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值