Potential issue with CHM.toArray
Paul Sandoz
paul.sandoz at oracle.com
Wed Aug 28 10:10:25 UTC 2013
Hi,
Intermittent failures were reported with the CHM toArray test in the JDK.
I updated the tests to increase the number of runs and the number of workers and i can reliably reproduce on my laptop, see below.
The test presumes the size should always increase but fails when it observes a new new size less than the previously observed size.
Is that a valid assumption? especially when resizing is in progress and bins are transferred from the old to the new table e.g. if one sets the initial capacity of the CHM in the test to say 8 * 1024 (double the number of entries) there is no issue.
The toArray implementation essentially uses the iterator, with some use of size estimates to create arrays with hopefully minimal re-sizing. So there is nothing particular about toArray regarding traversal.
Paul.
public class toArray {
public static void main(String[] args) throws Throwable {
for (int i = 0; i < 100; i++) {
main();
}
}
public static void main() throws Throwable {
final Throwable throwable[] = new Throwable[1];
final ConcurrentHashMap<Integer, Integer> m
= new ConcurrentHashMap<Integer, Integer>();
BiConsumer<Integer, Integer> r = (o, b) -> {
for (int i = o; i < b; i++)
m.put(i, i);
};
final int nWorkers = 4;
final int sizePerWorker = 1024;
final int maxSize = nWorkers * sizePerWorker;
List<Thread> workers = IntStream.range(0, nWorkers).
map(w -> w * sizePerWorker).
mapToObj(w -> (Runnable )() -> r.accept(w, w + sizePerWorker)).
map(Thread::new).collect(toList());
final Thread foreman = new Thread() {
public Throwable exception = null;
private int prevSize = 0;
private boolean checkProgress(Object[] a) {
int size = a.length;
System.out.println(size);
if (size < prevSize) throw new RuntimeException("WRONG WAY");
if (size > maxSize) throw new RuntimeException("OVERSHOOT");
if (size == maxSize) return true;
prevSize = size;
return false;
}
public void run() {
try {
Integer[] empty = new Integer[0];
while (true) {
if (checkProgress(m.values().toArray())) return;
if (checkProgress(m.keySet().toArray())) return;
if (checkProgress(m.values().toArray(empty))) return;
if (checkProgress(m.keySet().toArray(empty))) return;
}
} catch (Throwable t) {
throwable[0] = t;
}}};
foreman.start();
workers.stream().forEach(Thread::start);
workers.stream().forEach(toArray::join);
foreman.join();
if (throwable[0] != null)
throw throwable[0];
}
static void join(Thread t) {
try {
t.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
More information about the core-libs-dev
mailing list