Что самое худшее, что может случиться, если я напишу одновременно (из нескольких протекторов) в java.util.HashMap? - PullRequest
0 голосов
/ 29 июня 2018

У меня есть фон C ++, из которого я знаю, что одновременный доступ к записи на std::map может иметь очень неприятные последствия, какова ситуация в Java с java.util.HashMap?

Обратите внимание, что я хотел бы знать, есть ли плохие побочные эффекты помимо очевидного состояния гонки.

Насколько я понимаю, ConcurrentAccessException выбрасывается, только если вы перебираете java.util.HashMap, когда вы модифицируете его из другого потока, означает ли это, что безопасно просто вызывать метод get, пока другой поток вызывает put (с "безопасным" я имею в виду, что худшее, что может случиться, это то, что вы получили неправильное значение)?

Возможно ли как-то вызвать SEGFAULT подобным образом?

Обратите внимание, что под "подобным" я имею в виду условие гонки, которое включает только чистый метод / объекты Java (без JNI)

Ответы [ 3 ]

0 голосов
/ 29 июня 2018

Прежде всего, никогда не делайте этого, оберните карту в Collections.synchronizedMap, что достаточно просто.

Внутреннее состояние может быть повреждено, что может привести к любому из них:

[править] два новых предмета (два верхних)

  • Утечка памяти из-за того, что ключи попадают в неправильные сегменты и никогда не могут быть извлечены / удалены, пока не выполнено clear()
  • Бесконечные циклы из-за круглых циклов в хэш-таблицах
  • Предметы теряются (они будут собираться, если не используются где-либо еще)
  • Элементы, появляющиеся дважды для одного и того же ключа (при итерации)
  • Элементы, связанные с неправильным ключом
  • (новый) Итераторы могут неожиданно прекратить
  • Если на карте NavigableMap, вы можете испытать дополнительное раздражение

Серьезная ошибка, такая как segfault, не может произойти в Java, потому что это «безопасный» язык и в подобных ситуациях выдает NullPointerException.

0 голосов
/ 29 июня 2018

Худшее, что может случиться, включает в себя такие вещи, как:

  • ожидаемые исключения во время выполнения; например CCME
  • непредвиденные исключения во время выполнения (и т. Д. NPE),
  • неверные результаты; например get возвращает неправильное значение, put теряет записи или
  • бесконечные циклы (!).

Я видел отчеты обо всех них.

Причина в том, что если потоки не синхронизируются должным образом при использовании общего HashMap, тогда может быть:

  • проблемы из-за явных условий гонки или
  • проблемы из-за того, что один поток видит устаревшие значения из-за различного (разрешенного) поведения кэширования.

Возможно ли как-то вызвать SEGFAULT подобным образом?

Нет. Или, по крайней мере, если ваша кодовая база не включает в себя собственный код ИЛИ не использует Unsafe ИЛИ это не исправит ошибку JVM.

0 голосов
/ 29 июня 2018

Насколько я знаю, это явно небезопасно, и вы даже не должны рассматривать вызов методов HashMap из разных потоков. Также в Java вы, вероятно, не столкнетесь с SEGFAULT, как тот, с которым вы можете столкнуться в C и C ++.

Вместо этого вам следует рассмотреть возможность использования ConcurrentHashMap.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...