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 может или не может иметь метод, который делает то, что вам нужно атомарно.