1. Let’s start with a question

Q: What are the features of 1.7 and under what circumstances will deadlock occur

Let’s start with the put process

	 public V put(K key, V value) {
			if(table == EMPTY_TABLE) { inflateTable(threshold); // Initialize the linked list}if (key == null)
				returnputForNullKey(value); // Insert the node int whose key is nullhash = hash(key); / / calculatehashInt I = indexFor(hash, table.length); / / byhashTo calculate the indexfor(Entry<K,V> e = table[i]; e ! = null; e = e.next) { Object k; // Find the node with the same keyif (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
					V oldValue = e.value;
					e.value = value;
					e.recordAccess(this);
					returnoldValue; } } modCount++; // The number of changes +1 for the iterator addEntry(hash, key, value, i);
			return null;
		}
	void addEntry(int hash, K key, V value, int bucketIndex) {
        if((size >= threshold) && (null ! = table[bucketIndex])) { resize(2 * table.length);hash= (null ! = key) ?hash(key) : 0;
            bucketIndex = indexFor(hash, table.length);
        }

        createEntry(hash, key, value, bucketIndex); } private void inflateTable(int toSize) { // Find a power of 2 >= toSize int capacity = roundUpToPowerOf2(toSize); // Find the nearest power greater than toSize threshold = (int) math. min(capacity * loadFactor, MAXIMUM_CAPACITY + 1); table = new Entry[capacity]; initHashSeedAsNeeded(capacity); } /** * Initialize the hashing mask value. We defer initialization until we * really need it. */ final boolean InitHashSeedAsNeeded (int capacity) {// When you first come inhashSeed = 0, so currentAltHashing=false
        boolean currentAltHashing = hashSeed ! = 0; boolean useAltHashing = sun.misc.VM.isBooted() && (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD); boolean switching = currentAltHashing ^ useAltHashing; //currentfalse// equivalent to switching=useAltHashingif (switching) {
            hashSeed = useAltHashing
                ? sun.misc.Hashing.randomHashSeed(this)
                : 0;
        }
        return switching;
    }
	
	 final int hash(Object k) {
        int h = hashSeed; //hashSeed
        if (0 != h && k instanceof String) {
            returnsun.misc.Hashing.stringHash32((String) k); // If capacity // exceeds ALTERNATIVE_HASHING_THRESHOLD(i.e"jdk.map.althashing.threshold"Hashing. Murmur3_32 (); Hashing. } h ^= k.hashcode ();} h ^= k.hashcode (); // Thisfunction ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
	
	private static volatile boolean booted = false;
	 public static boolean isBooted() {
        returnbooted; // The return istrueVoid resize(int newCapacity) {Entry[] oldTable = table; void resize(int newCapacity) {Entry[] oldTable = table; int oldCapacity = oldTable.length;if (oldCapacity == MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable, initHashSeedAsNeeded(newCapacity)); table = newTable; threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1); } /** Multithreading is prone to create an infinite loop when moving arrays. Transfers all entries from current table to newTable. */ void Transfer (Entry[] newTable, Booleanrehash) {
        int newCapacity = newTable.length;
        for(Entry<K,V> e: table) {// Iterate over the table arraywhile(null ! = e) { Entry<K,V> next = e.next; // Thread 2 runs here and blocks // when thread 1 finishes expanding, (causing an inversion of position) // Thread 2's E and next are // pointing to thread 1's new pointer after expanding // thus making it possible for thread 2 to have a loop, resulting in an infinite loopif (rehash) {// Usually yesfalse@inithashSeedasneeded = null == e.key? Zero:hash(e.key); } int i = indexFor(e.hash, newCapacity); // Next points to a e.next = newTable[I]; // Next points to a e.next = newTable[I]; // Next points to a e.next = newTable[I]; // thread 2 newTable[I] = e; e = next; }}}Copy the code

conclusion

In transfer expansion, as 1.7 adopts the head insertion method, it is easy to cause the formation of rings in the case of multi-threading, which is the origin of deadlock.