Безопасна ли функция golang sync.Map Range? - PullRequest
0 голосов
/ 14 января 2019

Из документа

Range does not necessarily correspond to any consistent snapshot of the 
Map's contents: no key will be visited more than once, but if the value 
for any key is stored or deleted concurrently, Range may reflect any 
mapping for that key from any point during the Range call.

Означает ли это, что во время вызова диапазона не вызывается блокировка чтения, и пользователь должен реализовать свой собственный мьютекс, чтобы Range был безопасным для потока?

Ответы [ 2 ]

0 голосов
/ 14 января 2019

Прочитайте всю документацию, включая эту часть.

Синхронизация пакета

import "sync"

карта типа 1.9

Карта похожа на интерфейс Go map [interface {}] {}, но безопасна для одновременное использование несколькими программами без дополнительной блокировки или координация. Загрузка, хранение и удаление выполняется в амортизированной константе время.

Тип карты является специализированным. Большая часть кода должна использовать простую карту Go вместо этого, с отдельной блокировкой или координацией, для лучшей безопасности типа и чтобы было проще поддерживать другие инварианты вместе с картой содержание.

Тип карты оптимизирован для двух общих случаев использования: (1) когда запись для данного ключа пишется только один раз, но читается много раз, как в кэши, которые только растут, или (2) когда несколько операций чтения, записи, и перезаписать записи для непересекающихся наборов ключей. В этих двух случаях использование карты может значительно уменьшить конфликт блокировок по сравнению с Go карта в паре с отдельным Mutex или RWMutex.


По конструкции sync.Map является поточно-ориентированным. sync.Map - это карта специального назначения с ограниченным использованием.

Большая часть кода должна использовать простую карту Go, с отдельной блокировкой или координация, для лучшей безопасности типов и облегчения обслуживания другие инварианты вместе с содержимым карты.

Не добавляйте дополнительный слой блокировки к sync.Map. Используйте другой алгоритм или следуйте советам и используйте простой Go map с отдельной блокировкой или согласованием.


Синхронизация пакета

import "sync"

func (* Карта) Диапазон 1.9

func (m *Map) Range(f func(key, value interface{}) bool)

Диапазон вызывает f последовательно для каждого ключа и значения, присутствующего на карте. Если f возвращает false, диапазон останавливает итерацию.

Диапазон не обязательно соответствует любому последовательному снимку содержание карты: ни один ключ не будет посещен более одного раза, но если значение для любого ключа сохраняется или удаляется одновременно, диапазон может отражать любое сопоставление для этого ключа из любой точки во время вызова Range.

Диапазон может быть O (N) с количеством элементов на карте, даже если f возвращает false после постоянного числа вызовов.


Слабые инварианты sync.Map Range означают, что это часто не очень полезно.

0 голосов
/ 14 января 2019

Вы попали в это красивое место.

По сути, это работает так же, как если бы вы использовали for: вы просто захватываете счет и затем итерируете каждое значение, которое ожидаете существовать.

В идеале, если вам нужно беспокоиться о параллелизме на карте, вы должны сделать копию, которую затем повторяете, или внедрить sync.Mutex вокруг нее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...