44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668

Как устроена ConcurrentHashMap ?

26.05.2014, 17:41. Показов 6743. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Почитал про ConcurrentHashMap. Честно говоря куча вопросов.

значащие поля:
Java
1
2
3
4
5
 
    final Segment<K,V>[] segments;
    transient Set<K> keySet; 
    transient Set<Map.Entry<K,V>> entrySet; 
    transient Collection<V> values;
а что у нас было в HasMap:

Java
1
transient Entry[] table;
Что-то много всего добавили. Ведь Map.Entry и так содержит в себе и ключи и значения - зачем всё в кучу. Про сегменты пишут, что это типо как отдельные мапы...не совсем понятно.

Ну и наверное самый первый и важный вопрос - что вообще эта коллекция нам даёт то ? В HasMap в такой-то ситуации была проблема - в Concurrent реализации ее нет.

Добавлено через 1 час 4 минуты
Зачем нужны сегменты ? (знаю, что порой блокировка происходит посегментно)
По какому принципу попадают в сегменты?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
26.05.2014, 17:41
Ответы с готовыми решениями:

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

Как в Java устроена двоичная система?
Почему, например, двоичное 01111011 считается в Java, при переводе в десятичную как 123? Как я понял, тут и правда выходит 123, только...

Как устроена рекурсия?
Давно хотел спросить каким боком она работает? К примеру void RecFunction(int level) { if (level == 0) return; ...

20
Эксперт Java
 Аватар для KEKCoGEN
2399 / 2224 / 565
Регистрация: 28.12.2010
Сообщений: 8,672
26.05.2014, 18:29
Ответ в названии. ConcurrentHashMap поддерживает многопоточность. Отсюда и реализация. Вы можете вставить несколько элементов одновременно т.к есть сегменты.
0
44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668
26.05.2014, 19:21  [ТС]
KEKCoGEN, я хотел мягко говоря более подробного ответа)

И наверное даже догадываюсь кто его сможет дать))

Добавлено через 45 минут
Цитата Сообщение от KEKCoGEN Посмотреть сообщение
ConcurrentHashMap поддерживает многопоточность
ну и он в любом случае не один такой
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
26.05.2014, 20:20
На хабре есть небольшое описание CHMv7 - http://habrahabr.ru/post/132884/
В исходниках самого CHM можно найти небольшое описание алгоритма и принципа работы.

Для CHMv8 и для CHMv7

Что касается назначения: это thread-safe универсальная мапа, скорость работы которой масштабируется на множестве потоков.
0
44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668
26.05.2014, 21:49  [ТС]
turbanoff, Хабр уже читал, но там очень скупо написано.

попробую почитать исходники.

[QUOTE turbanoff]Что касается назначения: это thread-safe универсальная мапа, скорость работы которой масштабируется на множестве потоков.[/QUOTE]

Ну это да, я понял) Типо если мы просто обернем все методы syncronized, то блочим всю мапу, а тут как-то по сегментам. Но как-то такое описание меня не удовлетворяет).

В общем пока почитаю исходники)

Добавлено через 1 час 4 минуты
turbanoff, Почитал, что пишут в доке. Узнал, что эти сегменты "грузятся" по необходимости...

какого-то целостного представления так и нет(.

Java
1
static final class Segment<K,V> extends ReentrantLock implements Serializable {
а вот эта конструкция меня вообще путает. Вроде сами пишут в комменте, что Segment это HashMap, а сами наследуются от ReentrantLock. Разве тут есть отношение is-a ?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
26.05.2014, 22:29
Ну разумеется, Segment это не наследник HashMap, он просто устроен аналогичным образом.
Аналогичная таблица бакетов и поля threshold, modCount, loadFactor.

А наследником ReentrantLock-а его сделали, чтобы сэкономить на одном поле, и немного упростить код.
0
44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668
26.05.2014, 23:18  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
А наследником ReentrantLock-а его сделали, чтобы сэкономить на одном поле, и немного упростить код.
Не знаю как насчёт библиотек, а в обычном коде выглядело бы сомнительно. Я конечно понимаю где я и где Lee, но всё-таки.

а не подскажете ссылки на буржуйском хотя бы где разжёвано как это всё работает, а то по исходникам мне как-то совсем тяжело, а те ссылки, что были упомянуты не открыли мне глаза на правду. Я просто сам по себе знаю, что если ты знаешь истину, то тебе проще отличить плохую статью от хорошей.
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
26.05.2014, 23:57
Что-то не гуглится ничего стоящего. Вот тут есть схемы, возможно с ними станет понятнее - http://javaopensourcecode.blog... shmap.html
Если читать исходники CHM, то лучше взять из java 5 - там попроще и покороче. Посмотреть можно тут
1
44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668
27.05.2014, 00:08  [ТС]
turbanoff, спасибо, почитаю как руки дойдут.
0
44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668
27.05.2014, 18:09  [ТС]
Давайте порисуем)

вот наша до боли знакомая хэшмапа:

квадратики - бакеты
кружки объекты, которые разложены по бакетам.

сегмент это набор бакетов ?
Миниатюры
Как устроена ConcurrentHashMap ?  
0
44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668
27.05.2014, 18:35  [ТС]
ну то есть давайте от структуры данных плясать. в коде мы можем иметь указатели на всё что угодно в любых количествах, но думаю не будет проблем с пониманием, если нарисовать.

Добавлено через 12 минут
Как определяется позиция для вставки:

считаем hascode

первые 4 символа определяют сегмент. получается, что мы ограничены 9999 сегментами ?

остальные - определяют бакет.

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

Добавлено через 6 минут
Remove Entry

HashEntry is an immutable class so the next link can't be adjusted. All entries following removed node stays in the list, but all preceding ones need to be cloned.
прошу разжевать)
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
27.05.2014, 22:11
Цитата Сообщение от gredwhite Посмотреть сообщение
а может ли быть так, что бакеты пересекаются между сегментами. ну то есть может ли бакет быть вхож в 2 сегмента сразу?
Нет, ведь сегмент - это и есть набор бакетов.
Цитата Сообщение от gredwhite Посмотреть сообщение
прошу разжевать)
Когда вы делаете список, у вас в каждой ноде должен храниться указатель на следующий элемент.
Если вы делаете ноды неизменямыми, то получается что этот указатель нельзя поменять после создания ноды.
При удалении элемента из списка вам нужно поменять указатель в предыдущем элементе, но вы не можете его менять - и поэтому приходится создавать новую ноду. Так вы создали новую ноду, то в указатель, записанный в предыдущем от предыдущего, перестал был правильным - вам надо будет и его пересоздавать.
То есть при удалении приходится пересоздавать все ноды в списке, до текущего. Все последующие можно оставить так как есть, в них ничего менять не нужно.
0
44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668
28.05.2014, 02:26  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
Когда вы делаете список, у вас в каждой ноде должен храниться указатель на следующий элемент.
Если вы делаете ноды неизменямыми, то получается что этот указатель нельзя поменять после создания ноды.
При удалении элемента из списка вам нужно поменять указатель в предыдущем элементе, но вы не можете его менять - и поэтому приходится создавать новую ноду. Так вы создали новую ноду, то в указатель, записанный в предыдущем от предыдущего, перестал был правильным - вам надо будет и его пересоздавать.
То есть при удалении приходится пересоздавать все ноды в списке, до текущего. Все последующие можно оставить так как есть, в них ничего менять не нужно.
нода == бакет?

у сегмента список бакетов. об этом речь или о чем-то другом?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
28.05.2014, 02:38
нет. Нода, это не бакет.
Сегмент состоит из массива бакетов. В бакет попадают элементы, у которых hashCode одинаковые (или почти одинаковые). Чтобы хранить такие элементы отдельный бакет представляет из себя односвязный список. Элемент этого списка - это и есть нода (HashEnty).

Сегмент - практически полный аналог обычной HashMap. Возможно стоит повторить её устройство.
1
44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668
28.05.2014, 10:17  [ТС]
turbanoff, ааааа всё понял) просто иногда терминология путает)

Но пересоздавание списка нод ведь нужно только при удалении ?

я думал, что новая нода всегда добавляется в конец, а получается, что скорее всего в начало списка для улучшения производительности?

А сегменты всегда имеют одинаковое количество бакетов или это как-то балансируется в зависимости от нагрузки?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
28.05.2014, 17:24
Цитата Сообщение от gredwhite Посмотреть сообщение
Но пересоздавание списка нод ведь нужно только при удалении ?
При удалении и при расширении массива HashEntry<K,V>[] table.

Цитата Сообщение от gredwhite Посмотреть сообщение
я думал, что новая нода всегда добавляется в конец, а получается, что скорее всего в начало списка для улучшения производительности?
Да, в начало:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 412:         V put(K key, int hash, V value, boolean onlyIfAbsent) {
 413:             lock();
 414:             try {
 415:                 int c = count;
 416:                 if (c++ > threshold) // ensure capacity
 417:                     rehash();
 418:                 HashEntry<K,V>[] tab = table;
 419:                 int index = hash & (tab.length - 1);
 420:                 HashEntry<K,V> first = tab[index];
 421:                 HashEntry<K,V> e = first;
 422:                 while (e != null && (e.hash != hash || !key.equals(e.key)))
 423:                     e = e.next;
 424: 
 425:                 V oldValue;
 426:                 if (e != null) {
 427:                     oldValue = e.value;
 428:                     if (!onlyIfAbsent)
 429:                         e.value = value;
 430:                 }
 431:                 else {
 432:                     oldValue = null;
 433:                     ++modCount;
 434:                     tab[index] = new HashEntry<K,V>(key, hash, first, value); //<--Вот тут создается новая нода и становится в начало списка
 435:                     count = c; // write-volatile
 436:                 }
 437:                 return oldValue;
 438:             } finally {
 439:                 unlock();
 440:             }
 441:         }
Цитата Сообщение от gredwhite Посмотреть сообщение
А сегменты всегда имеют одинаковое количество бакетов или это как-то балансируется в зависимости от нагрузки?
Вроде каждый живет своей жизнью.
0
44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668
28.05.2014, 18:18  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
Сегмент состоит из массива бакетов
Цитата Сообщение от turbanoff Посмотреть сообщение
Чтобы хранить такие элементы отдельный бакет представляет из себя односвязный список. Элемент этого списка - это и есть нода (HashEnty).
против
Цитата Сообщение от turbanoff Посмотреть сообщение
При удалении и при расширении массива HashEntry<K,V>[] table.
так ноды хранятся в списке или массиве всё-таки?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
28.05.2014, 19:52
HashEntry<K,V>[] table - это массив односвязных списков.
Чтобы хранить ссылку на односвязный список нужно всего лишь хранить ссылку на его первый элемент. Вот в массиве и хранятся ссылки на первые элементы списков.
Каждый такой список я и называю бакетом.
0
44 / 44 / 11
Регистрация: 21.01.2013
Сообщений: 668
29.05.2014, 00:06  [ТС]
При удалении и при расширении массива HashEntry<K,V>[] table.
То есть другими словами при удалении ноды и в тех случаях, когда "нагруженность" мапы(или в данном случае сегмента?) превышает некоторое установленное значение.

Я так понимаю, что в этом случае перефигачивается(пересчитываются места куда кладутся элементы) весь сегмент(всё таки наверное не мапа)
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
29.05.2014, 14:55
Лучший ответ Сообщение было отмечено gredwhite как решение

Решение

gredwhite, Да, всё верно.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
29.05.2014, 14:55
Помогаю со студенческими работами здесь

Как устроена графика?
Я сделал программу с минимумом графики на чистом WinApi. Приведу конкретный пример: WM_PAINT: Нарисована гайка. При наведении на окно...

Как устроена корзина?
Допустим, я для корзины выделил 10 Гб. Что происходит, когда эти 10 Гб заканчиваются: нужно удалить ещё один файл FileForRECYCLER, а места...

Как устроена плавающая запятая?
Вводится число в 10-ой системе счисления и переводится в форму с плавающей запятой дробь двоичной. Помогите разобраться на примере. ...

Как устроена задержка в TTimer?
Мне необходимо несколько раз в секунду выполнять некоторую функцию, выполнение которой занимает длительное время. Предположим, что нужно...

Как устроена функция rand()
Объясните пожалуйста как работает функция rand(). Допустим нужно найти кол-во элементов равное 0 в динамическом массиве который состоит из...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

Новые блоги и статьи
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: показать затраченные материалы за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В качестве. . .
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2. Задача: отобразить спецтехнику, которая на данный момент находится в ремонте. Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
Памятка для бота и "визитка" для читателей "Semantic Universe Layer (Слой семантической вселенной)"
Hrethgir 19.04.2026
Сгенерировано для краткого описания по случаю сборки и компиляции скелета серверного приложения. И пусть после этого скажут, что статьи сгенерированные AI - туфта и не интересно. И это не реклама -. . .
Запрет удаления строк ТЧ документа при определённом условии
Maks 19.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "Аккумуляторы", разработанного в конфигурации КА2. У данного документа есть ТЧ, в которой в зависимости от прав доступа. . .
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут Суть: - Группа наркоманов из 10 человек. - Только один инфицирован ВИЧ. - Колются одной иглой. - Колются раз в день. - Колются последовательно через. . .
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru