2013-10-07 5 views
5

Я прочитал, что хеш-таблицы являются потокобезопасными, потому что они синхронизированы. рассмотрите этот фрагмент кодаhashtable и синхронизация в Java

if(!hashtable.contains(key)){ 
hashtable.put(key,value); 
} 

Операции с хэш-таблицей могут не синхронизироваться. например, если Thread t1 получает доступ к hastable и проверяет наличие ключа, и в то же время Thread t2 проверяет ключ, прежде чем t1 выполнит put. теперь два потока находятся внутри блока if и происходит перезапись значения ключа.

поэтому синхронизированный блок необходим.

synchronized { 
if(!hashtable.contains(key)){ 
    hashtable.put(key,value); 
    } 
} 

Это понимание правильное? или безопасен для операций, которые выполняются на hastables. Я получил это сомнение, пока я читал это post on race condition

+0

Да, это правильно. – SJuan76

ответ

9

Вы правы, что вам нужен блок synchronized. Методы Hashtable's: synchronized, но у вас все еще есть возможность участвовать в гонке при вызове нескольких методов вне блока synchronized. Встроенная синхронизация предотвращает проблемы, когда два потока одновременно называют put.

Вы также можете посмотреть в ConcurrentHashMap

3

Hashtable методов синхронизированы, но только обеспечивает защиту методы уровня от условий гонки. (Так что Hashtable — в отличие от HashMap — не будет внутренне поврежден, если несколько потоков одновременно пытаются изменить данные.) Только в этом смысле Hashtable является потокобезопасным.

Ни Hashtable, ни ConcurrentHashMap будет обеспечивать синхронизацию более высокого уровня, который обычно * то, что вам нужно, когда вы выполняете многоэтапные операции. В любом случае вам нужен внешний блок synchronized, поэтому вы можете использовать нижнюю служебную информацию HashMap, а не Hashtable.

  * Как Джефф Стори указывает, ConcurrentHashMap имеет метод putIfAbsent, который делает именно то, что вы делаете в вашем коде. Для других многоступенчатых операций ConcurrentHashMap может иметь или не иметь способ, который делает то, что вам нужно атомарно.

+1

'ConcurrentHashMap' имеет метод' putIfAbsent', который будет атомно проверять на предмет сдерживания ключа и помещать его, если он не существует. –

+0

@JeffStorey - Да, забыл об этом. Спасибо. Я соответствующим образом обновлю ответ. Тем не менее, для других многошаговых операций может потребоваться внешняя синхронизация. –