源码

数据结构

ArrayList

代码块JAVA · 506 行收起展开
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    private static final long serialVersionUID = 8683452581122892189L;

    /**
     * 默认初始容量大小
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 空数组(用于空实例)。
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    //用于默认大小空实例的共享空数组实例。
    //我们把它从EMPTY_ELEMENTDATA数组中区分出来,以知道在添加第一个元素时容量需要增加多少。
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 保存ArrayList数据的数组
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * ArrayList 所包含的元素个数
     */
    private int size;

    /**
     * 带初始容量参数的构造函数(用户可以在创建ArrayList对象时自己指定集合的初始大小)
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            //如果传入的参数大于0,创建initialCapacity大小的数组
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            //如果传入的参数等于0,创建空数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            //其他情况,抛出异常
            throw new IllegalArgumentException("Illegal Capacity: " +
                    initialCapacity);
        }
    }

    /**
     * 默认无参构造函数
     * DEFAULTCAPACITY_EMPTY_ELEMENTDATA 为0.初始化为10,也就是说初始其实是空数组 当添加第一个元素的时候数组容量才变成10
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
     */
    public ArrayList(Collection<? extends E> c) {
        //将指定集合转换为数组
        elementData = c.toArray();
        //如果elementData数组的长度不为0
        if ((size = elementData.length) != 0) {
            // 如果elementData不是Object类型数据(c.toArray可能返回的不是Object类型的数组所以加上下面的语句用于判断)
            if (elementData.getClass() != Object[].class)
                //将原来不是Object类型的elementData数组的内容,赋值给新的Object类型的elementData数组
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // 其他情况,用空数组代替
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

    /**
     * 修改这个ArrayList实例的容量是列表的当前大小。 应用程序可以使用此操作来最小化ArrayList实例的存储。
     */
    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
                    ? EMPTY_ELEMENTDATA
                    : Arrays.copyOf(elementData, size);
        }
    }
//下面是ArrayList的扩容机制
//ArrayList的扩容机制提高了性能,如果每次只扩充一个,
//那么频繁的插入会导致频繁的拷贝,降低性能,而ArrayList的扩容机制避免了这种情况。

    /**
     * 如有必要,增加此ArrayList实例的容量,以确保它至少能容纳元素的数量
     *
     * @param minCapacity 所需的最小容量
     */
    public void ensureCapacity(int minCapacity) {
        // 如果不是默认空数组,则minExpand的值为0;
        // 如果是默认空数组,则minExpand的值为10
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                // 如果不是默认元素表,则可以使用任意大小
                ? 0
                // 如果是默认空数组,它应该已经是默认大小
                : DEFAULT_CAPACITY;

        // 如果最小容量大于已有的最大容量
        if (minCapacity > minExpand) {
            // 根据需要的最小容量,确保容量足够
            ensureExplicitCapacity(minCapacity);
        }
    }

    // 根据给定的最小容量和当前数组元素来计算所需容量。
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        // 如果当前数组元素为空数组(初始情况),返回默认容量和最小容量中的较大值作为所需容量
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        // 否则直接返回最小容量
        return minCapacity;
    }

    // 确保内部容量达到指定的最小容量。
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    //判断是否需要扩容
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            //调用grow方法进行扩容,调用此方法代表已经开始扩容了
            grow(minCapacity);
    }

    /**
     * 要分配的最大数组大小
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * ArrayList扩容的核心方法。
     */
    private void grow(int minCapacity) {
        // oldCapacity为旧容量,newCapacity为新容量
        int oldCapacity = elementData.length;
        //将oldCapacity 右移一位,其效果相当于oldCapacity /2,
        //我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        //再检查新容量是否超出了ArrayList所定义的最大容量,
        //若超出了,则调用hugeCapacity()来比较minCapacity和 MAX_ARRAY_SIZE,
        //如果minCapacity大于MAX_ARRAY_SIZE,则新容量则为Integer.MAX_VALUE,否则,新容量大小则为 MAX_ARRAY_SIZE。
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    //比较minCapacity和 MAX_ARRAY_SIZE
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
    }

    /**
     * 返回此列表中的元素数。
     */
    public int size() {
        return size;
    }

    /**
     * 如果此列表不包含元素,则返回 true 。
     */
    public boolean isEmpty() {
        //注意=和==的区别
        return size == 0;
    }

    /**
     * 如果此列表包含指定的元素,则返回true 。
     */
    public boolean contains(Object o) {
        //indexOf()方法:返回此列表中指定元素的首次出现的索引,如果此列表不包含此元素,则为-1
        return indexOf(o) >= 0;
    }

    /**
     * 返回此列表中指定元素的首次出现的索引,如果此列表不包含此元素,则为-1
     */
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i] == null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                //equals()方法比较
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    /**
     * 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。.
     */
    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size - 1; i >= 0; i--)
                if (elementData[i] == null)
                    return i;
        } else {
            for (int i = size - 1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    /**
     * 返回此ArrayList实例的浅拷贝。 (元素本身不被复制。)
     */
    public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            //Arrays.copyOf功能是实现数组的复制,返回复制后的数组。参数是被复制的数组和复制的长度
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // 这不应该发生,因为我们是可以克隆的
            throw new InternalError(e);
        }
    }

    /**
     * 以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。
     * 返回的数组将是“安全的”,因为该列表不保留对它的引用。
     * (换句话说,这个方法必须分配一个新的数组)。
     * 因此,调用者可以自由地修改返回的数组结构。
     * 注意:如果元素是引用类型,修改元素的内容会影响到原列表中的对象。
     * 此方法充当基于数组和基于集合的API之间的桥梁。
     */
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

    /**
     * 以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素);
     * 返回的数组的运行时类型是指定数组的运行时类型。 如果列表适合指定的数组,则返回其中。
     * 否则,将为指定数组的运行时类型和此列表的大小分配一个新数组。
     * 如果列表适用于指定的数组,其余空间(即数组的列表数量多于此元素),则紧跟在集合结束后的数组中的元素设置为null 。
     * (这仅在调用者知道列表不包含任何空元素的情况下才能确定列表的长度。)
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            // 新建一个运行时类型的数组,但是ArrayList数组的内容
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        //调用System提供的arraycopy()方法实现数组之间的复制
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

    // Positional Access Operations

    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

    /**
     * 返回此列表中指定位置的元素。
     */
    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

    /**
     * 用指定的元素替换此列表中指定位置的元素。
     */
    public E set(int index, E element) {
        //对index进行界限检查
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        //返回原来在这个位置的元素
        return oldValue;
    }

    /**
     * 将指定的元素追加到此列表的末尾。
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //这里看到ArrayList添加元素的实质就相当于为数组赋值
        elementData[size++] = e;
        return true;
    }

    /**
     * 在此列表中的指定位置插入指定的元素。
     * 先调用 rangeCheckForAdd 对index进行界限检查;然后调用 ensureCapacityInternal 方法保证capacity足够大;
     * 再将从index开始之后的所有成员后移一个位置;将element插入index位置;最后size加1。
     */
    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //arraycopy()这个实现数组之间复制的方法一定要看一下,下面就用到了arraycopy()方法实现数组自己复制自己
        System.arraycopy(elementData, index, elementData, index + 1,
                size - index);
        elementData[index] = element;
        size++;
    }

    /**
     * 删除该列表中指定位置的元素。 将任何后续元素移动到左侧(从其索引中减去一个元素)。
     */
    public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index + 1, elementData, index,
                    numMoved);
        elementData[--size] = null; // clear to let GC do its work
        //从列表中删除的元素
        return oldValue;
    }

    /**
     * 从列表中删除指定元素的第一个出现(如果存在)。 如果列表不包含该元素,则它不会更改。
     * 返回true,如果此列表包含指定的元素
     */
    public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

    /*
     * 该方法为私有的移除方法,跳过了边界检查,并且不返回被移除的值。
     */
    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index + 1, elementData, index,
                    numMoved);
        elementData[--size] = null; // 在移除元素后,将该位置的元素设为 null,以便垃圾回收器(GC)能够回收该元素。
    }

    /**
     * 从列表中删除所有元素。
     */
    public void clear() {
        modCount++;

        // 把数组中所有的元素的值设为null
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

    /**
     * 按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾。
     */
    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    /**
     * 将指定集合中的所有元素插入到此列表中,从指定的位置开始。
     */
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount

        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                    numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

    /**
     * 从此列表中删除所有索引为fromIndex (含)和toIndex之间的元素。
     * 将任何后续元素移动到左侧(减少其索引)。
     */
    protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = size - toIndex;
        //arraycopy(源数组, 源起始位置, 目标数组, 目标起始位置, 复制长度)
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                numMoved);

        // clear to let GC do its work, 范围置null
        int newSize = size - (toIndex - fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }

    /**
     * 检查给定的索引是否在范围内。
     */
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * add和addAll使用的rangeCheck的一个版本
     */
    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * 返回IndexOutOfBoundsException细节信息
     */
    private String outOfBoundsMsg(int index) {
        return "Index: " + index + ", Size: " + size;
    }

    /**
     * 从此列表中删除指定集合中包含的所有元素。
     */
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        //如果此列表被修改则返回true
        return batchRemove(c, false);
    }

    /**
     * 仅保留此列表中包含在指定集合中的元素。
     * 换句话说,从此列表中删除其中不包含在指定集合中的所有元素。
     */
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }

    /**
     * 从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。
     * 指定的索引表示初始调用将返回的第一个元素为next 。 初始调用previous将返回指定索引减1的元素。
     * 返回的列表迭代器是fail-fast 。
     */
    public ListIterator<E> listIterator(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: " + index);
        return new ListItr(index);
    }

    /**
     * 返回列表中的列表迭代器(按适当的顺序)。
     * 返回的列表迭代器是fail-fast 。
     */
    public ListIterator<E> listIterator() {
        return new ListItr(0);
    }

    /**
     * 以正确的顺序返回该列表中的元素的迭代器。
     * 返回的迭代器是fail-fast 。
     */
    public Iterator<E> iterator() {
        return new Itr();
    }

HashMap

代码块JAVA · 359 行收起展开
package codex.read.datastruct;  
import java.io.Serializable;  
import java.util.AbstractMap;  
import java.util.Map;  
  
// 基于 OpenJDK 8 摘出的 HashMap 核心源码。  
// 重点看底层存储、扩容/搬移、查找/插入/删除路径。  
public abstract class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable {  
  
    // 序列化版本号。  
    private static final long serialVersionUID = 362498820763181265L;  
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;  
    static final int MAXIMUM_CAPACITY = 1 << 30;  
    static final float DEFAULT_LOAD_FACTOR = 0.75f;  
    static final int TREEIFY_THRESHOLD = 8;  
    static final int UNTREEIFY_THRESHOLD = 6;  
    static final int MIN_TREEIFY_CAPACITY = 64;  
  
    // 这是当前类的内部辅助类型,用来封装节点、视图或同步逻辑。  
    static class Node<K, V> implements Map.Entry<K, V> {  
        final int hash;  
        final K key;  
  
        // 当前持有的值或状态。  
        V value;  
        Node<K, V> next;  
  
        // 初始化当前对象的核心状态。  
        Node(int hash, K key, V value, Node<K, V> next) {  
            this.hash = hash;  
            this.key = key;  
            this.value = value;  
            this.next = next;  
        }  
  
        // 读取当前状态或指定位置的元素。  
        public final K getKey() {  
            return key;  
        }  
  
        // 读取当前状态或指定位置的元素。  
        public final V getValue() {  
            return value;  
        }  
  
        // 写入新值,并按约定返回结果。  
        public final V setValue(V newValue) {  
            V oldValue = value;  
            value = newValue;  
            return oldValue;  
        }  
    }  
  
    // 哈希桶数组,节点最终都落在这里。  
    transient Node<K, V>[] table;  
  
    // 当前结构中元素的数量。  
    transient int size;  
    transient int modCount;  
  
    // 下一次触发扩容的阈值。  
    int threshold;  
  
    // 负载因子,用来平衡空间占用和哈希碰撞。  
    final float loadFactor;  
  
    // 初始化当前对象的核心状态。  
    public HashMap() {  
        this.loadFactor = DEFAULT_LOAD_FACTOR;  
    }  
  
    // 初始化当前对象的核心状态。  
    public HashMap(int initialCapacity, float loadFactor) {  
  
        // 先判断当前条件是否成立,成立才走这个分支。  
        if (initialCapacity < 0) {  
            throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);  
        }  
  
        // 先判断当前条件是否成立,成立才走这个分支。  
        if (initialCapacity > MAXIMUM_CAPACITY) {  
            initialCapacity = MAXIMUM_CAPACITY;  
        }  
  
        // 先判断当前条件是否成立,成立才走这个分支。  
        if (loadFactor <= 0 || Float.isNaN(loadFactor)) {  
            throw new IllegalArgumentException("Illegal load factor: " + loadFactor);  
        }  
        this.loadFactor = loadFactor;  
        this.threshold = tableSizeFor(initialCapacity);  
    }  
  
    // 对原始 hash 再做一次扰动,尽量让桶分布更均匀。  
    static final int hash(Object key) {  
        int h;  
        //别让原始 hash 太规整低位变化少 高位变化多  
        // 把 hash 的高位信息折叠到低位里, &偏向0, |偏向1, 趋同性强, 相同为0不同为1, 没有偏置 ^最适合  
        /*  
          * 0x12340001            0x56780001            0x9ABC0001           &15-->0001全撞一个桶上了  
        * */        return key == null ? 0 : (h = key.hashCode()) ^ (h >>> 16);  
    }  
  
    //把你传进来的容量 cap,调整成“大于等于 cap 的最小 2 的幂”  
    static final int tableSizeFor(int cap) {  
        /*  
        *10000000        |01000000       = 11000000        *        * */        // 当 `cap` 本身已经是 2 的幂时,结果还能保持原值, 16->32  
        int n = cap - 1;  
        n |= n >>> 1;  
        n |= n >>> 2;  
        n |= n >>> 4;  
        n |= n >>> 8;  
        n |= n >>> 16;  
  
        // 先判断当前条件是否成立,成立才走这个分支。  
        if (n < 0) {  
            return 1;  
        }  
        return n >= MAXIMUM_CAPACITY ? MAXIMUM_CAPACITY : n + 1;  
    }  
  
  
    // 读取当前状态或指定位置的元素。  
    public V get(Object key) {  
        Node<K, V> e = getNode(hash(key), key);  
        return e == null ? null : e.value;  
    }  
  
  
    //hashmap通过 hash&(len-1) 找到桶下标, 再根据hash和key比较找到对应节点 (单靠hash可能有哈希碰撞)  
    final Node<K, V> getNode(int hash, Object key) {  
        Node<K, V>[] tab = table;  
        int n;  
        Node<K, V> first;  
        Node<K, V> e;  
        K k;  
  
        // 数组非空, 数组首节点非空  
        if (tab != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) {  
  
            // 先查首节点是否是要找的数 key == null ? 0 : (h = key.hashCode()) ^ (h >>> 16);            if (first.hash == hash && ((k = first.key) == key || (key != null && key.equals(k)))) {  
                return first; //hash相同未必就是要找的, 还要看key  
            }  
            e = first.next;  
            // 首节点不是, 继续往下找  
            while (e != null) {  
  
                // 只有对象存在时,后面的逻辑才有意义。  
                if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {  
                    return e;  
                }  
                e = e.next;  
            }  
        }  
        return null;  
    }  
  
  
    // 把键值对写入当前结构。  
    public V put(K key, V value) {  
        return putVal(hash(key), key, value, false, true);  
    }  
  
    // 这是 HashMap 真正写入节点的核心路径。  
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {  
        Node<K, V>[] tab = table;  
  
        // 先处理空值,避免后面继续访问时出问题。  
        if (tab == null || tab.length == 0) {  
            tab = resize();  
        }  
  
        int n = tab.length;  
  
        //找桶下标  
        int i = (n - 1) & hash;  
  
        //对应下标的链表首节点  
        Node<K, V> p = tab[i];  
  
        // 如果为空, 创建节点  
        if (p == null) {  
            tab[i] = newNode(hash, key, value, null);  
        }  
  
  
        // 前面的条件都不满足时,走兜底分支。  
        else {  
            //非空, 开始遍历找点  
            Node<K, V> e = p;  
            K k;  
  
            // 检查首节点, 发现key存在, 先存下来, 后续再改val 注意这里是  p && (key同一个引用 || key逻辑一直"abc"=="abc")  
            if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))) ) {  
                e = p;  
            }  
  
            // 前面的条件都不满足时,走兜底分支。  
            else {  
                int binCount = 0;  
                while (true) {  
  
                    // 发现走到链表的尽头都没有, 那么创建吧, 然后if完了有e=e.next; 后又有e.hash=hash, break  
                    if (e.next == null) {  
                        e.next = newNode(hash, key, value, null);  
  
                        // 先判断当前条件是否成立,成立才走这个分支。  
                        if (binCount >= TREEIFY_THRESHOLD - 1) {  
                            treeifyBin(tab, hash);  
                        }  
                        break;  
                    }  
                    e = e.next;  
  
                    // 边走链表变检查, 发现有这个key的节点  
                    if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {  
                        break;  
                    }  
                    binCount++;  
                }  
            }  
  
            // 此时 首节点是 | 链表有 | 链表没有, 所有逻辑都走完了, e必定有值了于是赋新值给他, 这里的e!=null疑似多余? gpt讲讲  
            if (e != null && e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {  
                V oldValue = e.value;  
  
                // 先处理空值,避免后面继续访问时出问题。  
                if (!onlyIfAbsent || oldValue == null) {  
                    e.value = value;  
                }  
                return oldValue;  
            }  
        }  
        modCount++;  
  
        // 先判断当前条件是否成立,成立才走这个分支。  
        if (++size > threshold) {  
            resize();  
        }  
        return null;  
    }  
  
    // 扩容并迁移旧桶中的节点。  
    final Node<K, V>[] resize() {  
        Node<K, V>[] oldTab = table;  
        int oldCap = oldTab == null ? 0 : oldTab.length;  
        int oldThr = threshold;  
        int newCap;  
        int newThr = 0;  
  
        // 先判断当前条件是否成立,成立才走这个分支。  
        if (oldCap > 0) {  
            newCap = oldCap << 1;  
  
            // 先判断当前条件是否成立,成立才走这个分支。  
            if (newCap > MAXIMUM_CAPACITY) {  
                newCap = MAXIMUM_CAPACITY;  
            }  
            newThr = (int) (newCap * loadFactor);  
        }  
  
        // 上一个条件没命中时,再继续判断这个分支。  
        else if (oldThr > 0) {  
            newCap = oldThr;  
        }  
  
        // 前面的条件都不满足时,走兜底分支。  
        else {  
            newCap = DEFAULT_INITIAL_CAPACITY;  
            newThr = (int) (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);  
        }  
  
        // 先判断当前条件是否成立,成立才走这个分支。  
        if (newThr == 0) {  
            newThr = (int) (newCap * loadFactor);  
        }  
  
  
        threshold = newThr;  
        @SuppressWarnings("unchecked")  
        Node<K, V>[] newTab = (Node<K, V>[]) new Node[newCap];  
        table = newTab;  
  
        // 只有对象存在时,后面的逻辑才有意义。  
        if (oldTab != null) {  
            for (Node<K, V> e : oldTab) {  
                while (e != null) {  
                    Node<K, V> next = e.next;  
                    //迁移旧表的节点映射到新表, 本该  hash%len, 但是太慢, 由于是2的幂, 所以等价于(newCap-1)&hash  
                    int index = (newCap - 1) & e.hash;  
                    e.next = newTab[index];  
                    newTab[index] = e;  
                    e = next;  
                }  
            }  
        }  
        return newTab;  
    }  
  
    // 桶内节点过多时,尝试把链表转成红黑树。 链表>8 && 数组>64  
    void treeifyBin(Node<K, V>[] tab, int hash) {  
  
        // 先处理空值,避免后面继续访问时出问题。  
        if (tab == null || tab.length < MIN_TREEIFY_CAPACITY) {  
            resize();  
        }  
    }  
  
  
    Node<K, V> newNode(int hash, K key, V value, Node<K, V> next) {  
        return new Node<>(hash, key, value, next);  
    }  
  
    // 删除目标元素,并维护结构的一致性。  
    public V remove(Object key) {  
        Node<K, V>[] tab = table;  
  
        // 先处理空值,避免后面继续访问时出问题。  
        if (tab == null || tab.length == 0) {  
            return null;  
        }  
  
        int hash = hash(key);  
        int index = (tab.length - 1) & hash;  
        Node<K, V> prev = null;  
        Node<K, V> e = tab[index];  
  
        while (e != null) {  
            Node<K, V> next = e.next;  
  
            // 只有对象存在时,后面的逻辑才有意义。 //引用一致or内容一致  
            if (e.hash == hash && (e.key == key || (key != null && key.equals(e.key)))) {  
  
                // 如果是首节点, 那么要设置继任者  
                if (prev == null) {  
                    tab[index] = next;  
                }  
  
                // 不是首节点, 就删掉cur  
                else {  
                    prev.next = next;  
                }  
                size--;  
                modCount++;  
                return e.value;  
            }  
            prev = e;  
            e = next;  
        }  
        return null;  
    }  
  
    // 返回当前结构里真实持有的元素个数。  
    public int size() {  
        return size;  
    }  
    public boolean isEmpty() {  
        return size == 0;  
    }  
}

JUC

AbstractQueuedSynchronizer

代码块JAVA · 386 行收起展开
 AQS 核心源码解析

  一、核心字段

  public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer {

      // 等待队列的头节点(哨兵节点,不代表任何线程)
      private transient volatile Node head;

      // 等待队列的尾节点
      private transient volatile Node tail;

      // 同步状态,语义由子类定义
      private volatile int state;

      // 继承自AbstractOwnableSynchronizer,记录当前持有独占锁的线程
      private transient Thread exclusiveOwnerThread;
  }

  二、Node节点

  static final class Node {
      // 两种模式
      static final Node SHARED = new Node();   // 共享模式标记
      static final Node EXCLUSIVE = null;      // 独占模式标记

      // waitStatus的四种值
      static final int CANCELLED =  1;  // 线程取消了,跳过这个节点
      static final int SIGNAL    = -1;  // 后继节点需要被唤醒
      static final int CONDITION = -2;  // 在Condition队列中
      static final int PROPAGATE = -3;  // 共享模式下释放需要向后传播

      volatile int waitStatus;      // 默认0
      volatile Node prev;           // 前驱
      volatile Node next;           // 后继
      volatile Thread thread;       // 这个节点代表的线程
      Node nextWaiter;              // Condition队列中的下一个节点,或者SHARED/EXCLUSIVE标记
  }

  waitStatus的含义是对后继节点的承诺,不是自己的状态。SIGNAL意思是"我释放的时候要唤醒后面的人"。节点刚创建时waitStatus=0,是后继节点入队后把前驱改成SIGNAL的。

  三、独占模式——获取

  // ========== 对外入口 ==========
  public final void acquire(int arg) {
      if (!tryAcquire(arg) &&                        // 1. 尝试获取(子类实现)
          acquireQueued(addWaiter(Node.EXCLUSIVE), arg))  // 2. 入队 + 3. 自旋阻塞
          selfInterrupt();  // 补上在阻塞期间被吞掉的中断标记
  }

  // ========== tryAcquire:子类实现 ==========
  // AQS自己不实现,直接抛UnsupportedOperationException
  // 以ReentrantLock非公平锁为例:
  protected boolean tryAcquire(int acquires) {
      final Thread current = Thread.currentThread();
      int c = getState();
      if (c == 0) {
          // 没人占,CAS抢
          if (compareAndSetState(0, acquires)) {
              setExclusiveOwnerThread(current);
              return true;
          }
      } else if (current == getExclusiveOwnerThread()) {
          // 自己占的,重入,state累加
          int nextc = c + acquires;
          if (nextc < 0) throw new Error("Maximum lock count exceeded");
          setState(nextc);  // 不需要CAS,因为是自己持有锁的情况下改的
          return true;
      }
      return false;
  }

  // ========== addWaiter:封装成Node加入队尾 ==========
  private Node addWaiter(Node mode) {
      Node node = new Node(Thread.currentThread(), mode);

      // 快速尝试:直接CAS挂到队尾
      Node pred = tail;
      if (pred != null) {
          node.prev = pred;
          if (compareAndSetTail(pred, node)) {
              pred.next = node;
              return node;
          }
      }

      // 快速尝试失败(队列为空或CAS竞争失败)→ 自旋入队
      enq(node);
      return node;
  }

  private Node enq(final Node node) {
      for (;;) {  // 自旋,保证一定入队成功
          Node t = tail;
          if (t == null) {
              // 队列还没初始化,创建哨兵节点作为head
              if (compareAndSetHead(new Node()))
                  tail = head;
              // 注意这里没return,下一轮循环才把真正的node挂上去
          } else {
              node.prev = t;
              if (compareAndSetTail(t, node)) {
                  t.next = node;
                  return t;
              }
          }
      }
  }

  先设prev再CAS设tail,这个顺序很重要。如果先CAS成功再设prev,中间有一瞬间tail.prev是null,其他线程从tail往前遍历就会断链。所以AQS里从后往前遍历是安全的,从前往后遍
  历不一定安全(next可能还没设上)。

  // ========== acquireQueued:入队后自旋+阻塞 ==========
  final boolean acquireQueued(final Node node, int arg) {
      boolean failed = true;
      try {
          boolean interrupted = false;
          for (;;) {
              final Node p = node.predecessor();  // 拿前驱

              // 前驱是head(我排第一个)→ 再试一次tryAcquire
              if (p == head && tryAcquire(arg)) {
                  // 拿到了!把自己设为新head(变成哨兵)
                  setHead(node);  // head = node; node.thread = null; node.prev = null;
                  p.next = null;  // 旧head断开引用,help GC
                  failed = false;
                  return interrupted;
              }

              // 没拿到,判断是否该阻塞
              if (shouldParkAfterFailedAcquire(p, node) &&
                  parkAndCheckInterrupt())
                  interrupted = true;
          }
      } finally {
          if (failed)
              cancelAcquire(node);  // 异常退出时取消节点
      }
  }

  // ========== shouldParkAfterFailedAcquire:设置前驱的SIGNAL + 清理CANCELLED节点 ==========
  private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
      int ws = pred.waitStatus;

      if (ws == Node.SIGNAL)
          // 前驱已经是SIGNAL了,我可以安心park
          return true;

      if (ws > 0) {
          // 前驱是CANCELLED状态,往前找到一个正常的节点作为前驱
          do {
              node.prev = pred = pred.prev;
          } while (pred.waitStatus > 0);
          pred.next = node;
          // 返回false,回到acquireQueued的for循环再试一轮
      } else {
          // ws是0或PROPAGATE,CAS改成SIGNAL
          compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
          // 返回false,再循环一次确认
      }
      return false;
  }

  为什么不直接park,要先把前驱设成SIGNAL?因为release的时候是通过检查head的waitStatus来决定要不要唤醒后继的。如果前驱的waitStatus不是SIGNAL,release就不会唤醒你,你
  就永远醒不过来了。

  // ========== parkAndCheckInterrupt:真正阻塞 ==========
  private final boolean parkAndCheckInterrupt() {
      LockSupport.park(this);       // 阻塞在这里,线程挂起
      return Thread.interrupted();  // 醒来后检查是否被中断过
  }

  四、独占模式——释放

  public final boolean release(int arg) {
      if (tryRelease(arg)) {               // 子类实现:state减,归零则返回true
          Node h = head;
          if (h != null && h.waitStatus != 0)
              unparkSuccessor(h);          // 唤醒后继
          return true;
      }
      return false;
  }

  // 以ReentrantLock为例:
  protected boolean tryRelease(int releases) {
      int c = getState() - releases;
      if (Thread.currentThread() != getExclusiveOwnerThread())
          throw new IllegalMonitorStateException();  // 不是持有者不能释放
      boolean free = false;
      if (c == 0) {
          // state归零,锁完全释放
          free = true;
          setExclusiveOwnerThread(null);
      }
      setState(c);  // 不需要CAS,因为是持有锁的线程在操作
      return free;
  }

  // ========== unparkSuccessor:唤醒后继节点 ==========
  private void unparkSuccessor(Node node) {
      int ws = node.waitStatus;
      if (ws < 0)
          compareAndSetWaitStatus(node, ws, 0);  // 把head的waitStatus清回0

      // 找到后继中第一个需要唤醒的节点
      Node s = node.next;
      if (s == null || s.waitStatus > 0) {
          // next为空或已取消 → 从tail往前找
          s = null;
          for (Node t = tail; t != null && t != node; t = t.prev)
              if (t.waitStatus <= 0)
                  s = t;  // 不break,一直往前找,最终s是离head最近的有效节点
      }
      if (s != null)
          LockSupport.unpark(s.thread);  // 唤醒
  }

  为什么从tail往前找而不是从head往后找?因为enq()里是先设prev再CAS设tail最后设next,next可能还没来得及设。从前往后遍历可能丢节点,从后往前通过prev遍历是安全的。

  五、共享模式——获取

  public final void acquireShared(int arg) {
      if (tryAcquireShared(arg) < 0)   // 子类实现,返回值<0表示获取失败
          doAcquireShared(arg);
  }

  private void doAcquireShared(int arg) {
      final Node node = addWaiter(Node.SHARED);  // 入队,模式是SHARED
      boolean failed = true;
      try {
          boolean interrupted = false;
          for (;;) {
              final Node p = node.predecessor();
              if (p == head) {
                  int r = tryAcquireShared(arg);
                  if (r >= 0) {
                      // 获取成功!
                      // 和独占模式的关键区别在这里:
                      setHeadAndPropagate(node, r);
                      p.next = null;
                      if (interrupted) selfInterrupt();
                      failed = false;
                      return;
                  }
              }
              if (shouldParkAfterFailedAcquire(p, node) &&
                  parkAndCheckInterrupt())
                  interrupted = true;
          }
      } finally {
          if (failed) cancelAcquire(node);
      }
  }

  // ========== setHeadAndPropagate:共享模式的传播唤醒 ==========
  private void setHeadAndPropagate(Node node, int propagate) {
      Node h = head;
      setHead(node);  // 自己变成新head

      // 关键:如果还有剩余资源(propagate > 0),或者旧head/新head的waitStatus < 0
      // 就继续唤醒后面的节点
      if (propagate > 0 || h == null || h.waitStatus < 0 ||
          (h = head) == null || h.waitStatus < 0) {
          Node s = node.next;
          if (s == null || s.isShared())
              doReleaseShared();  // 继续唤醒后面的共享节点
      }
  }

  这就是共享模式和独占模式的核心区别:独占模式拿到锁就完了,共享模式拿到资源后还要看看后面有没有人也能拿到,有的话继续唤醒,形成链式传播。Semaphore(3)三个许可,队列
  里等着三个线程,释放一个许可 → 唤醒第一个 → 第一个发现还有剩余 → 唤醒第二个 → 以此类推。

  六、共享模式——释放

  public final boolean releaseShared(int arg) {
      if (tryReleaseShared(arg)) {
          doReleaseShared();
          return true;
      }
      return false;
  }

  private void doReleaseShared() {
      for (;;) {
          Node h = head;
          if (h != null && h != tail) {
              int ws = h.waitStatus;
              if (ws == Node.SIGNAL) {
                  // CAS把SIGNAL改成0,成功则唤醒后继
                  if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                      continue;
                  unparkSuccessor(h);
              } else if (ws == 0 &&
                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                  // ws已经是0了(刚被清过),设成PROPAGATE确保传播不中断
                  continue;
          }
          if (h == head)  // head没变说明没有新的线程被唤醒并抢到资源,退出
              break;
          // head变了说明有线程拿到了资源把自己设成了新head,再循环一次处理新head
      }
  }

  七、Condition队列

  public class ConditionObject implements Condition {
      // Condition自己维护一个单向等待队列,和AQS的CLH队列是两个独立的队列
      private transient Node firstWaiter;
      private transient Node lastWaiter;

      // ========== await:释放锁 + 进入Condition队列阻塞 ==========
      public final void await() throws InterruptedException {
          if (Thread.interrupted()) throw new InterruptedException();

          Node node = addConditionWaiter();   // 1. 创建CONDITION节点,加入Condition队列尾部
          int savedState = fullyRelease(node); // 2. 完全释放锁(state清零),保存之前的state值
                                               //    必须完全释放,不管重入了几次

          int interruptMode = 0;
          while (!isOnSyncQueue(node)) {       // 3. 检查自己是否已被移回CLH队列
              LockSupport.park(this);          //    没有就阻塞
              if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                  break;
          }

          // 4. 被signal唤醒后,重新进入CLH队列竞争锁
          if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
              interruptMode = REINTERRUPT;

          // 5. 清理Condition队列中已取消的节点
          if (node.nextWaiter != null)
              unlinkCancelledWaiters();
          if (interruptMode != 0)
              reportInterruptAfterWait(interruptMode);
      }

      // ========== signal:把Condition队列头节点移回CLH队列 ==========
      public final void signal() {
          if (!isHeldExclusively())             // 必须持有锁才能signal
              throw new IllegalMonitorStateException();
          Node first = firstWaiter;
          if (first != null)
              doSignal(first);
      }

      private void doSignal(Node first) {
          do {
              // 把firstWaiter指向下一个,摘掉当前头节点
              if ((firstWaiter = first.nextWaiter) == null)
                  lastWaiter = null;
              first.nextWaiter = null;
          } while (!transferForSignal(first) &&    // 移回CLH队列
                   (first = firstWaiter) != null);  // 如果失败(节点取消了),试下一个
      }
  }

  // ========== transferForSignal:从Condition队列移回CLH队列 ==========
  final boolean transferForSignal(Node node) {
      // CAS把waitStatus从CONDITION改成0,失败说明节点已取消
      if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
          return false;

      // enq入队到CLH队列尾部,返回前驱节点
      Node p = enq(node);
      int ws = p.waitStatus;
      // 把前驱设成SIGNAL,确保前驱释放时会唤醒自己
      if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
          LockSupport.unpark(node.thread);  // 前驱已取消或CAS失败,直接唤醒
      return true;
  }

  两个队列的流转:

  signal()                          await()
  Condition队列 ──────→ CLH队列 ──────→ Condition队列

  线程调await():
    1. 从CLH队列出来(释放锁)
    2. 进Condition队列阻塞

  别的线程调signal():
    1. 把Condition队列头节点移到CLH队列尾部
    2. 那个线程醒来后在CLH队列里重新竞争锁

  ---

ReentrantLock

代码块JAVA · 260 行收起展开
package codex.read.locks;  
import java.io.Serializable;  
import java.util.concurrent.TimeUnit;  
  
import java.util.concurrent.locks.Condition;  
import java.util.concurrent.locks.Lock;  
  
// 基于 OpenJDK 8 摘出的 ReentrantLock 核心源码。  
// 重点看 state、队列节点、获取锁失败后的入队与唤醒。  
public class ReentrantLock implements Lock, Serializable {  
  
    // 序列化版本号。  
    private static final long serialVersionUID = 7373984872572414699L;  
    private final Sync sync;  
  
  
    // 这是当前类的内部辅助类型,用来封装节点、视图或同步逻辑。 AQS的子类  
    abstract static class Sync extends AbstractQueuedSynchronizer {  
  
        // 序列化版本号。  
        private static final long serialVersionUID = -5179523762034025860L;  
        abstract void lock();  
  
  
        //在没人持有的时候cas尝试获取锁,  acquires是指本次要加几层重入  
        /*nonfairTryAcquire(int acquires) 里的 acquires 表示本次获取锁希望增加的同步状态值。  
        在 ReentrantLock 里,state 表示锁的重入次数,  
        所以 acquires 通常就是 1,表示获取一层锁。  
        第一次加锁时会把 state 从 0 改成 1,重入时会把 state 在原有基础上再加 1。  
        它不是历史获取次数,而是本次 acquire 操作对应的增量。*/  
  
        //condition.await(); 可能会一次性把所有所释放, 所以这里不写死为1, lock()通常是1  
        final boolean nonfairTryAcquire(int acquires) {  
            final Thread current = Thread.currentThread();  
            int c = getState(); // sync继承自aqs的state字段  
  
            // state == 0, 无人持有, 尝试cas  
            if (c == 0) {  
                // 如果cas成功, 那么设置独占锁为当前线程  
                if (compareAndSetState(0, acquires)) {  
                    setExclusiveOwnerThread(current);  
                    return true;  
                }  
            }  
  
            // 有人持锁, 是不是当前线程持有锁  
            else if (current == getExclusiveOwnerThread()) {  
                int nextc = c + acquires;  
  
                // nc小于零, 说明太多线程了, 溢出了, 抛出异常  
                if (nextc < 0) {  
                    throw new Error("Maximum lock count exceeded");  
                }  
                //说明是重入锁, 重置state字段  
                setState(nextc);  
                return true;  
            }  
            //有人持锁并且不是当前线程, 获取锁失败, false  
            return false;  
        }  
  
  
  
        //尝试释放锁, 入参是  
        protected final boolean tryRelease(int releases) {  
            int c = getState() - releases;  
  
            // 是你的锁吗你就释放!  
            if (Thread.currentThread() != getExclusiveOwnerThread()) {  
                throw new IllegalMonitorStateException();  
            }  
  
            boolean free = false;  
  
            // state==0, 说明当前没线程了, 设置为free, 当前独占线程为null  
            if (c == 0) {  
                free = true;  
                setExclusiveOwnerThread(null);  
            }  
  
            setState(c);  
  
            //state==0, 才算释放成功, 否则就是重入锁--罢了  
            return free;  
        }  
  
        //是独占锁吗  
        protected final boolean isHeldExclusively() {  
            return getExclusiveOwnerThread() == Thread.currentThread();  
        }  
  
  
        final ConditionObject newCondition() {  
            return new ConditionObject();  
        }  
  
        // 读取当前状态或指定位置的元素。  
  
        final Thread getOwner() {  
            return getState() == 0 ? null : getExclusiveOwnerThread();  
        }  
  
        // 当前锁的持有几重?  
        final int getHoldCount() {  
            return isHeldExclusively() ? getState() : 0;  
        }  
  
        //state!=0  
        final boolean isLocked() {  
            return getState() != 0;  
        }  
  
    }  
  
  
    // 非公平, 继承自sync  
    static final class NonfairSync extends Sync {  
  
        // 序列化版本号。  
        private static final long serialVersionUID = 7316153563782823691L;  
  
        // 尝试获取当前锁或同步状态。  
        final void lock() {  
  
            // 先判断当前条件是否成立,成立才走这个分支。  
            if (compareAndSetState(0, 1)) {  
                setExclusiveOwnerThread(Thread.currentThread());  
            }  
  
            // 前面的条件都不满足时,走兜底分支。  
            else {  
                acquire(1);  
            }  
        }  
        protected final boolean tryAcquire(int acquires) {  
            return nonfairTryAcquire(acquires);  
        }  
    }  
  
  
    // 公平锁  
    static final class FairSync extends Sync {  
  
        // 序列化版本号。  
        private static final long serialVersionUID = -3000897897090466540L;  
  
        // 尝试获取当前锁或同步状态。  
        final void lock() {  
            acquire(1);  
        }  
  
  
        protected final boolean tryAcquire(int acquires) {  
            final Thread current = Thread.currentThread();  
            int c = getState();  
  
            // 当前无人  
            if (c == 0) {  
  
                // 由于是公平锁, 所以要看是否有人在排队, 没有才cas  
                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;  
        }  
    }  
  
    // 默认非公平锁, 抢到就走, 避免徒耗性能  
    public ReentrantLock() {  
        sync = new NonfairSync();  
    }  
  
    // 初始化当前对象的核心状态。  
    public ReentrantLock(boolean fair) {  
        sync = fair ? new FairSync() : new NonfairSync();  
    }  
  
  
    // 尝试获取当前锁或同步状态。  
    public void lock() {  
        sync.lock();  
    }  
  
    // 尝试获取当前锁或同步状态。  
    public void lockInterruptibly() throws InterruptedException {  
        sync.acquireInterruptibly(1);  
    }  
  
  
    public boolean tryLock() {  
        return sync.nonfairTryAcquire(1);  
    }  
  
  
    public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {  
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));  
    }  
  
    // 释放当前持有的锁或同步状态。  
    public void unlock() {  
        sync.release(1);  
    }  
  
  
    public Condition newCondition() {  
        return sync.newCondition();  
    }  
  
    // 读取当前状态或指定位置的元素。  
    public int getHoldCount() {  
        return sync.getHoldCount();  
    }  
  
  
    public boolean isHeldByCurrentThread() {  
        return sync.isHeldExclusively();  
    }  
  
  
    public boolean isLocked() {  
        return sync.isLocked();  
    }  
  
  
    public final boolean isFair() {  
        return sync instanceof FairSync;  
    }  
  
    // 读取当前状态或指定位置的元素。  
    protected Thread getOwner() {  
        return sync.getOwner();  
    }  
  
  
    public final boolean hasQueuedThreads() {  
        return sync.hasQueuedThreads();  
    }  
  
  
  
  
  
  
  
}

ReentrantReadWriteLock

代码块JAVA · 376 行收起展开
package codex.read.locks;  
import java.io.Serializable;  
import java.util.concurrent.TimeUnit;  
  
import java.util.concurrent.locks.Condition;  
import java.util.concurrent.locks.Lock;  
import java.util.concurrent.locks.ReadWriteLock;  
  
// 基于 OpenJDK 8 摘出的 ReentrantReadWriteLock 核心源码。  
// 重点看 state、队列节点、获取锁失败后的入队与唤醒。  
public class ReentrantReadWriteLock implements ReadWriteLock, Serializable {  
  
    // 序列化版本号。  
    private static final long serialVersionUID = -6992448646407690164L;  
    final Sync sync;  
    private final ReadLock readerLock;  
    private final WriteLock writerLock;  
  
  
    // 这是当前类的内部辅助类型,用来封装节点、视图或同步逻辑。  
  
  
    abstract static class Sync extends AbstractQueuedSynchronizer {  
  
        // 序列化版本号。  
        private static final long serialVersionUID = 6317671515068378041L;  
  
        /*在 ReentrantReadWriteLock 里,  
            state 不是一个普通整数. 它被拆成了两半:  
            高 16 位:读锁数量  
            低 16 位:写锁重入次数  
            高读 低写  
         */  
        static final int SHARED_SHIFT = 16;  
  
        static final int SHARED_UNIT = 1 << SHARED_SHIFT;  
  
        static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;  
  
        //0000 0000 0000 0000 1111 1111 1111 1111  
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;  
  
  
  
  
  
  
        private transient Thread firstReader;  
  
        private transient int firstReaderHoldCount;  
  
  
        //读锁是shareCount  
        static int sharedCount(int c) {  
            return c >>> SHARED_SHIFT;  
        }  
  
  
        //这个是说明写锁次数的  
        static int exclusiveCount(int c) {  
            return c & EXCLUSIVE_MASK;  
        }  
  
        abstract boolean readerShouldBlock();  
  
        abstract boolean writerShouldBlock();  
  
        //尝试释放  
        protected final boolean tryRelease(int releases) {  
  
            // 不是你的锁  
            if (!isHeldExclusively()) {  
                throw new IllegalMonitorStateException();  
            }  
            int nextc = getState() - releases;  
            boolean free = exclusiveCount(nextc) == 0;  
  
            // 先判断当前条件是否成立,成立才走这个分支。  
            if (free) {  
                setExclusiveOwnerThread(null);  
            }  
            setState(nextc);  
            return free;  
        }  
  
  
        /*如果当前锁已经有人占用了,  
            那我只有在“当前占用里包含写锁,并且这个写锁就是我自己持有”的情况下,  
            才允许继续获取。            其他情况全部失败。*/  
        protected final boolean tryAcquire(int acquires) {  
            Thread current = Thread.currentThread();  
            int c = getState();  
            int w = exclusiveCount(c);  
  
            // 1. 有人  
            /*要么有读锁  
              要么有写锁              要么两者都有某种组合*/  
            if (c != 0) {  
  
                // 1.1 没有写锁的out, 有写锁但是不是我的out  
                if (w == 0 || current != getExclusiveOwnerThread()) {  
                    return false;  
                }  
  
                //1.2 到这里的就是有写锁的我自己, 继续获取锁  
                //看看我有没有太过火  
                if (w + acquires > MAX_COUNT) {  
                    throw new Error("Maximum lock count exceeded");  
                }  
  
  
                setState(c + acquires);  
                return true;  
            }  
  
            //2. 当前没锁呢  
            // 2.1 如果初始化是fair, writerShouldBlock会去fairSync  
            /*boolean writerShouldBlock() {                return hasQueuedPredecessors(); //有无前驱节点  
            }*/            // 看看有没有前驱节点, ReentrantReadWriteLock是个公平的锁, 队伍有人我就不能插队啦  
  
            // 2.2 如果初始化是nonfair, writerShouldBlock会走NonFairSync的writerShouldBlock直接false  
            if (writerShouldBlock() || !compareAndSetState(c, c + acquires)) {  
                return false;  
            }  
            setExclusiveOwnerThread(current);  
            return true;  
        }  
  
  
        protected final boolean tryReleaseShared(int unused) {  
            int c = getState();  
            int nextc = c - SHARED_UNIT;//把 state 的高 16 位读锁计数减 1  
            // 先判断当前条件是否成立,成立才走这个分支。  
            if (Thread.currentThread() == firstReader) {  
                firstReaderHoldCount--;  
  
                // 先判断当前条件是否成立,成立才走这个分支。  
                if (firstReaderHoldCount == 0) {  
                    firstReader = null;  
                }  
            }  
  
            setState(nextc);  
  
            //此处应该是计算高16位是否为0, 因为高读低写  
            return sharedCount(nextc) == 0;  
        }  
  
  
        protected final int tryAcquireShared(int unused) {  
            Thread current = Thread.currentThread();  
            int c = getState();  
  
            // 有写锁  并且  不是当前线程占有独占锁  
            if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current) {  
                return -1;  
            }  
  
            // 是公平锁吗? 有人在前面吗? 我是第一读者吗?  
            if (readerShouldBlock() && firstReader != current) {  
                return -1;  
            }  
            int nextc = c + SHARED_UNIT;  
  
            // 先判断当前条件是否成立,成立才走这个分支。  
            if (sharedCount(nextc) > MAX_COUNT) {  
                throw new Error("Maximum lock count exceeded");  
            }  
            setState(nextc);  
  
            // 先处理空值,避免后面继续访问时出问题。  
            if (firstReader == null) {  
                firstReader = current;  
                firstReaderHoldCount = 1;  
            }  
  
            // 上一个条件没命中时,再继续判断这个分支。  
            else if (firstReader == current) {  
                firstReaderHoldCount++;  
            }  
            return 1;  
        }  
        final ConditionObject newCondition() {  
            return new ConditionObject();  
  
        }  
  
  
        protected final boolean isHeldExclusively() {  
            return getExclusiveOwnerThread() == Thread.currentThread();  
        }  
  
        // 读取当前状态或指定位置的元素。  
  
  
  
        final int getReadLockCount() {  
            return sharedCount(getState());  
        }  
  
        final boolean isWriteLocked() {  
            return exclusiveCount(getState()) != 0;  
        }  
  
        // 读取当前状态或指定位置的元素。  
        final int getWriteHoldCount() {  
            return isHeldExclusively() ? exclusiveCount(getState()) : 0;  
        }  
  
  
  
  
  
  
    }  
  
    // 这是当前类的内部辅助类型,用来封装节点、视图或同步逻辑。  
    static final class NonfairSync extends Sync {  
  
        // 序列化版本号。  
        private static final long serialVersionUID = -8159625535654395037L;  
        boolean readerShouldBlock() {  
            return false;  
        }  
        boolean writerShouldBlock() {  
            return false;  
        }  
    }  
  
    // 这是当前类的内部辅助类型,用来封装节点、视图或同步逻辑。  
    static final class FairSync extends Sync {  
  
        // 序列化版本号。  
        private static final long serialVersionUID = -2274990926593161451L;  
        boolean readerShouldBlock() {  
            return hasQueuedPredecessors();  
        }  
        boolean writerShouldBlock() {  
            return hasQueuedPredecessors();  
        }  
    }  
  
    // 这是当前类的内部辅助类型,用来封装节点、视图或同步逻辑。  
    public static class ReadLock implements Lock, Serializable {  
  
        // 序列化版本号。  
        private static final long serialVersionUID = -5992448646407690164L;  
        private final Sync sync;  
  
        // 初始化当前对象的核心状态。  
        protected ReadLock(ReentrantReadWriteLock lock) {  
            sync = lock.sync;  
        }  
  
        // 尝试获取当前锁或同步状态。  
        public void lock() {  
            sync.acquireShared(1);  
        }  
  
        // 尝试获取当前锁或同步状态。  
        public void lockInterruptibly() throws InterruptedException {  
            sync.acquireSharedInterruptibly(1);  
        }  
  
        public boolean tryLock() {  
            return sync.tryAcquireShared(1) >= 0;  
        }  
        public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {  
  
            return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));  
        }  
  
        // 释放当前持有的锁或同步状态。  
        public void unlock() {  
            sync.releaseShared(1);  
        }  
  
        public Condition newCondition() {  
            throw new UnsupportedOperationException();  
        }  
  
    }  
  
    // 这是当前类的内部辅助类型,用来封装节点、视图或同步逻辑。  
    public static class WriteLock implements Lock, Serializable {  
  
        // 序列化版本号。  
        private static final long serialVersionUID = -4992448646407690164L;  
        private final Sync sync;  
  
        // 初始化当前对象的核心状态。  
        protected WriteLock(ReentrantReadWriteLock lock) {  
            sync = lock.sync;  
        }  
  
        // 尝试获取当前锁或同步状态。  
        public void lock() {  
            sync.acquire(1);  
        }  
  
        // 尝试获取当前锁或同步状态。  
        public void lockInterruptibly() throws InterruptedException {  
            sync.acquireInterruptibly(1);  
        }  
  
        public boolean tryLock() {  
            return sync.tryAcquire(1);  
        }  
        public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {  
  
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));  
        }  
  
        // 释放当前持有的锁或同步状态。  
        public void unlock() {  
            sync.release(1);  
        }  
  
        public Condition newCondition() {  
            return sync.newCondition();  
        }  
    }  
  
    // 初始化当前对象的核心状态。  
    public ReentrantReadWriteLock() {  
        this(false);  
    }  
  
    // 初始化当前对象的核心状态。  
    public ReentrantReadWriteLock(boolean fair) {  
        sync = fair ? new FairSync() : new NonfairSync();  
        readerLock = new ReadLock(this);  
        writerLock = new WriteLock(this);  
    }  
    public ReadLock readLock() {  
        return readerLock;  
    }  
    public WriteLock writeLock() {  
        return writerLock;  
  
    }  
  
  
    public final boolean isFair() {  
        return sync instanceof FairSync;  
    }  
  
    // 读取当前状态或指定位置的元素。  
  
    public int getReadLockCount() {  
        return sync.getReadLockCount();  
    }  
  
    public boolean isWriteLocked() {  
        return sync.isWriteLocked();  
    }  
  
    // 读取当前状态或指定位置的元素。  
  
    public int getWriteHoldCount() {  
        return sync.getWriteHoldCount();  
    }  
  
  
  
  
  
  
  
  
  
  
  
  
  
}