У меня есть "простой" пример из 4-х классов, который надежно показывает непредвиденное поведение при синхронизации Java на нескольких машинах. Как вы можете прочитать ниже, учитывая контракт с ключевым словом java sychronized
, Broke Synchronization
никогда не должен печататься из класса TestBuffer.
Вот 4 класса, которые будут воспроизводить проблему (по крайней мере, для меня). Меня не интересует, как исправить этот сломанный пример, но скорее , почему он разбивает в первую очередь.
Проблема с синхронизацией - Controller.java
Ошибка синхронизации - SyncTest.java
Проблема с синхронизацией - TestBuffer.java
Ошибка синхронизации - Tuple3f.java
И вот результат, который я получаю при запуске:
java -cp . SyncTest
Before Adding
Creating a TestBuffer
Before Remove
Broke Synchronization
1365192
Broke Synchronization
1365193
Broke Synchronization
1365194
Broke Synchronization
1365195
Broke Synchronization
1365196
Done
UPDATE: @Gray имеет самый простой пример, который прорывается до сих пор. Его пример можно найти здесь: Странное состояние гонки JRC
Основываясь на обратной связи, полученной от других, похоже, что проблема может возникнуть на 64-разрядной версии 1.6.0_20-1.6.0_31 Java (неуверенности относительно новых 1.6.0) в Windows и OSX. Никто не смог воспроизвести проблему на Java 7. Для воспроизведения проблемы может потребоваться многоядерная машина.
ОРИГИНАЛЬНЫЙ ВОПРОС:
У меня есть класс, который предоставляет следующие методы:
- remove - удаляет данный элемент из списка
- getBuffer - Итерирует все элементы в списке
Я уменьшил проблему до двух функций ниже, оба из которых находятся в одном и том же объекте, и оба они synchronized
. Если я не ошибаюсь, "Broke Synchronization" никогда не должен печататься, потому что insideGetBuffer
всегда должен быть установлен на false до того, как ввести remove
. Тем не менее, в моем приложении он печатает "Broke Synchronization", когда у меня есть один поток, вызывающий многократно удалять, в то время как другие вызовы getBuffer неоднократно. Симптом заключается в том, что я получаю ConcurrentModificationException
.
См. также:
Очень странное состояние гонки, которое выглядит как проблема JRE
Отчет об ошибках Sun:
Это было подтверждено как ошибка в Java Sun. По-видимому, он зафиксирован (неосознанно?) В jdk7u4, но они не передали исправление в jdk6. Идентификатор ошибки: 7176993