HashMap y visibilidad

Javadoc de HashMap estados

si el mapa se modifica estructuralmente en cualquier momento después de que se crea el iterador, de cualquier manera, excepto a través del propio método de eliminación del iterador, el iterador emitirá una excepción ConcurrentModificationException.

Construí un código de muestra que, según la especificación, se supone que debe fallar casi inmediatamente y lanzar una ConcurrentModificationException;

Falló inmediatamente como se esperaba con Java 7pero (parece que) siempre funciona con Java 6 (es decir, no lanza la excepción prometida).

Nota: a veces no falla con Java 7 (digamos 1 vez de 20) - Supongo que tiene que ver con la programación de subprocesos (es decir, los 2 runnables no están intercalados).

¿Me estoy perdiendo de algo? ¿Por qué la versión ejecutada con Java 6 no lanza una excepción ConcurrentModificationException?

En esencia, hay 2 tareas ejecutables que se ejecutan en paralelo (se utiliza un countdowndownlatch para hacer que se inicien aproximadamente al mismo tiempo):

uno es agregar elementos al mapael otro está iterando sobre el mapa, leyendo las teclas y colocándolas en una matriz

El hilo principal luego verifica cuántas claves se han agregado a la matriz.

Salida típica de Java 7 (La iteración falla inmediatamente):

java.util.ConcurrentModificationException
MAX i = 0

Salida típica de Java 6 (la iteración completa pasa y la matriz contiene todas las claves agregadas):

MAX i = 99

Código utilizado:

public class Test1 {

    public static void main(String[] args) throws InterruptedException {
        final int SIZE = 100;
        final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        map.put(1, 1);
        map.put(2, 2);
        map.put(3, 3);
        final int[] list = new int[SIZE];
        final CountDownLatch start = new CountDownLatch(1);
        Runnable put = new Runnable() {
            @Override
            public void run() {
                try {
                    start.await();
                    for (int i = 4; i < SIZE; i++) {
                        map.put(i, i);
                    }
                } catch (Exception ex) {
                }
            }
        };

        Runnable iterate = new Runnable() {
            @Override
            public void run() {
                try {
                    start.await();
                    int i = 0;
                    for (Map.Entry<Integer, Integer> e : map.entrySet()) {
                        list[i++] = e.getKey();
                        Thread.sleep(1);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        };
        ExecutorService e = Executors.newFixedThreadPool(2);
        e.submit(put);
        e.submit(iterate);
        e.shutdown();

        start.countDown();
        Thread.sleep(100);
        for (int i = 0; i < SIZE; i++) {
            if (list[i] == 0) {
                System.out.println("MAX i = " + i);
                break;
            }
        }
    }
}

Nota: usar JDK 7u11 y JDK 6u38 (versión de 64 bits) en una máquina x86.

Respuestas a la pregunta(3)

Su respuesta a la pregunta