2015-08-27 4 views
1

Я читал, что в параллельном хэшмапе на Java возможны одновременные вставки, поскольку он разделен на сегменты, и для каждого сегмента выполняется отдельная блокировка. Но если две вставки будут происходить на одном и том же сегменте, то этих одновременных действий не произойдет. Вопрос в том, что произойдет в таком случае? Будет ли вторая вставка ждать до первого завершения или что?Параллельная установка hashmap Одновременная вставка

+0

Вы читали Javadocs для 'ConcurrentHashMap'? – Kayaman

+3

q1) он все еще работает, q2) да, второй должен ждать. Вы можете увеличить количество сегментов, если хотите уменьшить вероятность этого, но вам очень редко нужно. –

+0

@ Кайаман - Прочитайте javadocs, но не нашел ничего, связанного с моим вопросом. –

ответ

3

В общем, вы не должны быть слишком озабочены, как ConcurrentHashMap реализуется. Он просто соответствует контракту ConcurrentMap, который гарантирует, что возможны одновременные изменения.

Но ответ на ваш вопрос: да, одна вставка может дождаться завершения другого. Внутри он использует блокировки, которые гарантируют, что один поток ожидает, пока другой не выпустит блокировку. Класс Segment, используемый внутренне, фактически наследует от ReentrantLock. Вот сокращенный вариант Segmenet.put():

final V put(K key, int hash, V value, boolean onlyIfAbsent) { 
    HashEntry<K,V> node = tryLock() ? null : scanAndLockForPut(key, hash, value); 
    V oldValue; 
    try { 
     // modifications 
    } finally { 
     unlock(); 
    } 
    return oldValue; 
} 

private HashEntry<K,V> scanAndLockForPut(K key, int hash, V value) { 
    // ... 
    int retries = -1; // negative while locating node 
    while (!tryLock()) { 
     if (retries < 0) { 
      // ... 
     } 
     else if (++retries > MAX_SCAN_RETRIES) { 
      lock(); 
      break; 
     } 
     else if ((retries & 1) == 0 && (f = entryForHash(this, hash)) != first) { 
      e = first = f; // re-traverse if entry changed 
      retries = -1; 
     } 
    } 
    return node; 
} 

Это может дать вам идею.

0

Посмотрите на javadoc for ConcurrentMap. В нем описаны дополнительные методы, доступные для борьбы с одновременными мутациями карты.

1

Если 2 обновления пытаются произойти в одном сегменте, они будут вступать в противоречие друг с другом, и один из них должен будет ждать. Вы можете оптимизировать это, выбирая значение concurrencyLevel, которое учитывает количество потоков, которые будут одновременно обновлять хэш-карту.

Вы можете найти все детали в javadoc for the class

3

ConcurrentHashMap does not block when performing retrieval operations, and there is no locking for the usual operations.

Эвристика с большинством параллельных структур данных состоит в том, что сначала создается модифицированная структура данных, которая имеет переднюю структуру данных, видимую внешним методам. Затем, когда модификация завершена, структура данных резервного копирования создается публичной структурой данных, а структура общедоступных данных выталкивается обратно. Для этого есть что-то большее, но это типичный контракт.

+0

Спасибо ... но эта концепция структуры данных базы данных здесь для меня нова ... Не могли бы вы предоставить мне ссылку, где я могу прочитать об этом подробно? –

+0

В документации указано, что * операции поиска * не блокируются. Когда вы начинаете изменять, вы не можете обойтись без блокировок. – Mifeet

1

ConcurrentHashMap содержит массив сегментов, который, в свою очередь, содержит массив HashEntry. Каждый HashEntry содержит ключ, значение и указатель на следующую соседнюю запись.

Но он приобретает замок в сегменте. Следовательно, вы правы. то есть вторая вставка ждет, пока первый не будет завершен.