HashMap и видимость

HashMap»с Javadoc состояния:

если карта структурно изменена в любое время после создания итератора, любым способом, кроме как через итераторСобственный метод удаления, итератор сгенерирует исключение ConcurrentModificationException.

Я создал пример кода, который, основываясь на спецификации, должен почти сразу завершиться сбоем, и выдал исключение ConcurrentModificationException;

Сбой сразу же, как и ожидалось с Java 7но он (кажется) всегда работает с Java 6 (то есть он не выдает обещанное исключение).

Примечание: иногда это не дает сбоя в Java 7 (скажем, 1 раз из 20) - я полагаю, это связано с планированием потоков (то есть, 2 запускаемых объекта не чередуются).

Я что-то пропустил? Почему версия, запускаемая с Java 6, не генерирует исключение ConcurrentModificationException?

По сути, есть 2 запускаемые задачи, выполняющиеся параллельно (обратный отсчет используется, чтобы запустить их примерно одновременно):

один добавляет элементы на картудругая перебирает карту, читает ключи и помещает их в массив

Затем основной поток проверяет, сколько ключей было добавлено в массив.

Java 7 типичный вывод (итерация сразу завершается неудачей):

java.util.ConcurrentModificationException

MAX я = 0

Java 6 типичный вывод (вся итерация проходит, и массив содержит все добавленные ключи):

Макс я = 99

Используемый код:

public class Test1 {

    public static void main(String[] args) throws InterruptedException {
        final int SIZE = 100;
        final Map map = new HashMap();
        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 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;
            }
        }
    }
}

Примечание: использование JDK 7u11 и JDK 6u38 (64-битная версия) на компьютере с архитектурой x86.

Ответы на вопрос(3)

Ваш ответ на вопрос