Это побитовый оператор xor в java, который приводит к 1 для разного значения бит (т. е. 1 ^ 0 = 1) и 0 для одного значения бита (т. е. 0 ^ 0 = 0), когда число записывается в двоичной форме .
ex: -
Чтобы использовать ваш пример:
Бинарное представление 5 равно 0101. Бинарное представление 4 равно 0100.
Простым способом определения Побитового XOR является утверждение, что результат имеет 1 в каждом месте, где два входных числа отличаются.
0101 ^ 0100 = 0001 (5 ^ 4 = 1).
Да, это вызовет серьезные проблемы. Одним из примеров является то, что может произойти при добавлении значения в хэш-карту: это может вызвать перефразирование таблицы, и если это происходит, когда другой поток выполняет итерацию по списку столкновений (хэш-таблице «bucket»), этот поток может ошибочно не удается найти ключ, который существует на карте. HashMap
явно небезопасно для одновременного использования.
Используйте вместо этого ConcurrentHashMap
.
Да. Очень плохие вещи произойдут. Например, ваш поток может застрять в бесконечном цикле.
Либо используйте ConcurrentHashMap , либо NonBlockingHashMap
В случае сомнений проверьте Javadocs класса :
. Обратите внимание, что эта реализация не синхронизирована. Если несколько потоков обращаются к хэш-карте одновременно, и хотя бы один из потоков структурно изменяет карту, она должна быть синхронизирована извне. (Структурная модификация - это любая операция, которая добавляет или удаляет одно или несколько сопоставлений; простое изменение значения, связанного с ключом, который уже содержится в экземпляре, не является структурной модификацией.) Обычно это выполняется путем синхронизации с некоторым объектом, который естественным образом инкапсулирует карту , Если такого объекта не существует, карту следует «обернуть» с помощью метода Collections.synchronizedMap. Это лучше всего сделать во время создания, чтобы предотвратить случайный несинхронизированный доступ к карте:
Map m = Collections.synchronizedMap(new HashMap(...));
(акцент не мой)
Таким образом, на основе тот факт, что вы сказали, что ваши потоки будут удалять сопоставления с карты, ответ таков: да это определенно вызовет проблему, и да, это определенно небезопасно .
Важность синхронизации или использования ConcurrentHashMap не может быть занижена.
До тех пор, пока пару лет назад у меня не было ложного впечатления, мне не удавалось синхронизировать только операции размещения и удаления в HashMap. Это, конечно, очень опасно и фактически приводит к бесконечному циклу в HashMap.get () на некоторых (я думаю, ранних 1.5) jdk.
То, что я сделал пару лет назад (и на самом деле не должно быть сделано):
public MyCache {
private Map<String,Object> map = new HashMap<String,Object>();
public synchronzied put(String key, Object value){
map.put(key,value);
}
public Object get(String key){
// can cause in an infinite loop in some JDKs!!
return map.get(key);
}
}
РЕДАКТИРОВАТЬ : думал, что я добавлю пример того, что не делать (см. выше)
Условия, которые вы описываете, не будут удовлетворены HashMap
. Поскольку процесс обновления карты не является атомарным, вы можете встретить карту в недопустимом состоянии. Многократные записи могут оставить это в поврежденном состоянии. ConcurrentHashMap (1.5 или более поздняя версия) делает то, что вы хотите.
Я читал здесь или в другом месте, нет, у вас нет доступа из многопоточности, но никто не говорит, что на самом деле происходит.
Итак, сегодня я увидел (поэтому я отвечаю на этот старый вопрос) приложение, работающее в производстве с марта: 2, поставленные на тот же HashSet (тогда HashMap), вызывают перегрузку процессора (около 100%) и увеличение памяти на 3 ГБ, затем уменьшение на GC. Мы должны перезапустить приложение.
Если «одновременно» вы подразумеваете из нескольких потоков, то да, вам нужно заблокировать доступ к нему (или использовать ConcurrentHashMap или аналогичный, который делает блокировку за вас).
Нет, проблем не будет, если вы выполните следующее:
Поместите ваши данные в HashMap при первой загрузке одного потока, прежде чем произойдет какая-либо многопоточность. Это связано с тем, что процесс добавления данных изменяет значение modcount и отличается при первом добавлении (возвращается ноль) и замене данных (старые данные будут возвращены, но modcount не будет изменен). Modcount - это то, что делает итераторы отказоустойчивыми. Однако если вы используете get, ничего не будет повторяться, так что все в порядке.
Используйте одинаковые клавиши во всем приложении. Как только приложение запускается и загружает свои данные, никакие другие ключи не могут быть назначены этой карте. Таким образом, get либо получит устаревшие данные, либо данные, которые были вставлены свежими - проблем не будет.
Как и другие упомянутые выше, используйте ConcurrentHashMap или синхронизируйте карту при обновлении.