Javadoc для HashMap
состояний:
Обратите внимание, что эта реализация не синхронизируется. Если несколько потоков доступа к карте хешей одновременно, и по крайней мере один из потоков изменяет структуру структурно, это должно быть быть синхронизировано извне. (A структурная модификация - это любая операция, которая добавляет или удаляет одно или больше сопоставлений; просто изменение значения, связанного с ключом, которое уже содержит экземпляр , не является структурной модификацией.) Это , как правило, выполняется путем синхронизации на каком-либо объекте, естественно инкапсулирует карту. Если такой объект не существует, карта должна быть «завернута» с использованием метода Collections.synchronizedMap.
Так документы говорят, что вы должны синхронизации доступа как-то, но не сказать, что произойдет, если вы этого не сделаете. Это означает, что поведение, когда вы делаете это, - undefined - все ставки отключены.
Вы можете посмотреть на the source code for HashMap
самостоятельно. Сердце put
является:
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
(Edit - это реализация в Java 6. Java 8-х резко отличается - что усиливает точку)
Мы можем спекулировать о результатах, если попытаться два потока это одновременно - но это довольно сложно рассуждать. Иногда это приводит к двум записям с одним и тем же ключом, иногда это не так. Это зависит от времени.
TreeMap
put()
совершенно по-другому, и его причуды при злоупотреблении таким образом будут разными.
Любое такое поведение является причудой реализации, и реализация может измениться в будущем без предупреждения, потому что мы говорим о неопределенном поведении.Реализация не дает никаких обещаний вам, что это не будет:
- молча уронить записи
- идти в бесконечный цикл
NullPointerException
- исковые огромные объемы памяти
- развратить магазин, так что записи с другими ключами теряются
- сделать ранее удаленные записи повторно отображаться
- создавать записи, содержащие мусор из кучи m Эморите
- т.д.
Документов сделать состояния, модификации из других мест, в то время как Iterator
работает на объекте, заставят Iterator
, чтобы бросить ConcurrentModificationException
- но это другая забота от синхронизация и может произойти, если вы использовали SynchronizedMap
Подводя итог, не делайте этого.
Я думаю, что они всегда будут переопределять друг друга. Если вы не правильно синхронизируете его, вы, вероятно, получите параллельное исключение. –
Почему вы спрашиваете? неужели вы не собираетесь использовать контейнер без потоков в таком сценарии? –
Поскольку _both будет проверять перед put_, там у вас есть условие гонки: вставка не является атомной (единственной неделимой) операцией, но она состоит из по крайней мере двух операций, которые могут мешать, когда 'Ta' неправильно синхронизируется с' Tb' , –