ThreadLocalMap 的源码看起来会考虑一种哈希冲突的情况,但不是 ThreadLocal 本身实现了完美散列吗?
看 ThreadLocal 的源码,它利用魔数0x61c88647在 2 的幂为容量的哈希表上,能够完美散列,没有一个元素会哈希冲突。
private final int threadLocalHashCode = nextHashCode(); private static AtomicInteger nextHashCode = new AtomicInteger(); private static final int HASH_INCREMENT = 0x61c88647; private static int nextHashCode() { return nextHashCode.getAndAdd(HASH_INCREMENT); }
而且构造每个 ThreadLocal 时,使用了 AtomicInteger 来得到自己的哈希值,那么就算两个线程同时构造 ThreadLocal,两个 ThreadLocal 对象的哈希值也是不同的(这么理解,对吧?)。
综上,两个 ThreadLocal 对象在 ThreadLocalMap 不可能哈希冲突。
而你看下面这段源码,看起来会考虑一种哈希冲突的情况,但不是 ThreadLocal 本身实现了完美散列吗?:
private Entry getEntry(ThreadLocal<?> key) { int i = key.threadLocalHashCode & (table.length - 1); Entry e = table[i]; //根据下标获得的 entry 可能为 null //只有当 entry 非 null,且 key 为同一个对象时,才直接返回 value if (e != null && e.get() == key) return e; //否则 getEntryAfterMiss else return getEntryAfterMiss(key, i, e); } /** * Version of getEntry method for use when key is not found in * its direct hash slot. * * @param key the thread local object * @param i the table index for key's hash code * @param e the entry at table[i] * @return */ private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) { Entry[] tab = table; int len = tab.length; while (e != null) { ThreadLocal<?> k = e.get(); if (k == key) return e; if (k == null)//寻址的过程中,不巧发现了包含 null key 的 entry expungeStaleEntry(i); else//利用 nextIndex,寻址到冲突后的实际位置 i = nextIndex(i, len); e = tab[i]; } return null; }
或者说,我认为 getEntryAfterMiss 里面的return e;不可能被调用到,因为这种情况发生,就说明两个 ThreadLocal 对象的哈希值一样了,产生了哈希冲突。