hashtable и синхронизация в Java
Я прочитал, что хэш-таблицы являются потокобезопасными, потому что они синхронизированы. рассмотрим этот фрагмент кода
if(!hashtable.contains(key)){
hashtable.put(key,value);
}
операции над hashtable не могут быть синхронизированы. например, если Thread t1
доступ к hastable и проверить ключ и в то же время Thread t2
проверяет ключ, прежде чем t1 выполняет put. теперь два потока находятся внутри блока if и происходит перезапись значения ключа.
так синхронизированный блок необходим.
synchronized {
if(!hashtable.contains(key)){
hashtable.put(key,value);
}
}
это понимание правильное? или hastables безопасно на деятельностях которые выполнены на hastables. Я получил это сомнение, пока читал это сообщение о состоянии гонки
2 ответов
вы правы, что вам нужно synchronized
заблокировать. The Hashtable's
методы synchronized
, но у вас еще есть возможность иметь гонку при вызове нескольких методов за пределами synchronized
заблокировать. Встроенная синхронизация предотвращает проблемы при вызове двух потоков put
в то же время, например.
вы также можете посмотреть в ConcurrentHashMap
Hashtable
методы синхронизированы, но это обеспечивает только защиту на уровне метода от условий гонки. (Так что Hashtable
-в отличие от HashMap
-не будет внутренне поврежден, если несколько потоков одновременно пытаются изменить данные.) Только в этом смысле Hashtable
является потокобезопасным.
ни Hashtable
или ConcurrentHashMap
обеспечит синхронизацию более высокого уровня, которая обычно* что вам нужно, когда вы выполняете многоступенчатые операции. Вам нужен внешний synchronized
блок в любом случае, так что вы могли бы также использовать более низкие накладные расходы HashMap
, а не Hashtable
.
*как указывает Джефф стори,ConcurrentHashMap
есть putIfAbsent
метод, который делает именно то, что вы делаете в коде. Для других многоступенчатых операций, ConcurrentHashMap
может или не может иметь метод, который делает то, что вам нужно атомарно.