--- jsr166/src/jsr166e/Striped64.java 2013/01/14 01:59:15 1.8 +++ jsr166/src/jsr166e/Striped64.java 2014/05/04 22:38:19 1.9 @@ -111,32 +111,17 @@ abstract class Striped64 extends Number } /** - * Holder for the thread-local hash code. The code is initially - * random, but may be set to a different value upon collisions. + * ThreadLocal holding a single-slot int array holding hash code. + * Unlike the JDK8 version of this class, we use a suboptimal + * int[] representation to avoid introducing a new type that can + * impede class-unloading when ThreadLocals are not removed. */ - static final class HashCode { - static final Random rng = new Random(); - int code; - HashCode() { - int h = rng.nextInt(); // Avoid zero to allow xorShift rehash - code = (h == 0) ? 1 : h; - } - } + static final ThreadLocal threadHashCode = new ThreadLocal(); /** - * The corresponding ThreadLocal class + * Generator of new random hash codes */ - static final class ThreadHashCode extends ThreadLocal { - public HashCode initialValue() { return new HashCode(); } - } - - /** - * Static per-thread hash codes. Shared across all instances to - * reduce ThreadLocal pollution and because adjustments due to - * collisions in one table are likely to be appropriate for - * others. - */ - static final ThreadHashCode threadHashCode = new ThreadHashCode(); + static final Random rng = new Random(); /** Number of CPUS, to place bound on table size */ static final int NCPU = Runtime.getRuntime().availableProcessors(); @@ -199,8 +184,15 @@ abstract class Striped64 extends Number * @param hc the hash code holder * @param wasUncontended false if CAS failed before call */ - final void retryUpdate(long x, HashCode hc, boolean wasUncontended) { - int h = hc.code; + final void retryUpdate(long x, int[] hc, boolean wasUncontended) { + int h; + if (hc == null) { + threadHashCode.set(hc = new int[1]); // Initialize randomly + int r = rng.nextInt(); // Avoid zero to allow xorShift rehash + h = hc[0] = (r == 0) ? 1 : r; + } + else + h = hc[0]; boolean collide = false; // True if last slot nonempty for (;;) { Cell[] as; Cell a; int n; long v; @@ -253,6 +245,7 @@ abstract class Striped64 extends Number h ^= h << 13; // Rehash h ^= h >>> 17; h ^= h << 5; + hc[0] = h; // Record index for next time } else if (busy == 0 && cells == as && casBusy()) { boolean init = false; @@ -272,7 +265,6 @@ abstract class Striped64 extends Number else if (casBase(v = base, fn(v, x))) break; // Fall back on using base } - hc.code = h; // Record index for next time }