Одновременное чтение / запись снимка карты var - PullRequest
0 голосов
/ 15 октября 2018

Я сталкиваюсь с ситуацией, которую не могу понять.В моем коде я использую функции, которые требуют чтения карты (но не записи, а только циклический просмотр снимка существующих данных в этой карте).Вот мой код:

type MyStruct struct {
   *sync.RWMutex
   MyMap map[int]MyDatas
}

var MapVar = MyStruct{ &sync.RWMutex{}, make(map[int]MyDatas) }

func MyFunc() {
   MapVar.Lock()
   MapSnapshot := MapVar.MyMap
   MapVar.Unlock()
   for _, a := range MapSnapshot { // Map concurrent write/read occur here
      //Some stuff
   }
}

main() {
   go MyFunc()
}

Функция "MyFunc" запускается в подпрограмме go, только один раз, при этом многократные запуски этой функции не выполняются.Многие другие функции обращаются к тому же «MapVar» тем же методом, и он случайным образом создает «карту одновременной записи / чтения».Я надеюсь, что кто-то объяснит мне, почему мой код неправильный.

Спасибо за ваше время.

edit: Чтобы уточнить, я просто спрашиваю, почему мой диапазон MapSnapshot производит одновременную запись / запись карты /читать.Я не могу понять, как эту карту можно использовать одновременно, так как я сохраняю реальный глобальный var (MapVar) в локальном var (MapSnapshot), используя мьютекс синхронизации.

edit: Решено.Чтобы скопировать содержимое карты в новую переменную без использования той же ссылки (и, таким образом, чтобы избежать одновременного чтения / записи карты), я должен выполнить цикл по нему и записать каждый индекс и содержимое в новую карту с циклом for.

Спасибо xpare и nilsocket.

1 Ответ

0 голосов
/ 15 октября 2018

нет нескольких прогонов этой функции.Многие другие функции обращаются к тому же «MapVar» с помощью того же метода, и он случайным образом создает «карту одновременной записи / чтения»

Когда вы передаете значение MapVar.MyMap в MapSnapshot,Map concurrent write/read никогда не произойдет, потому что операция обернута мьютексом.

Но в цикле может произойти ошибка, так как практически процесс чтения происходит во время цикла.Поэтому лучше также обернуть цикл мьютексом.

MapVar.Lock() // lock begin

MapSnapshot := MapVar.MyMap
for _, a := range MapSnapshot {
   // Map concurrent write/read occur here
   // Some stuff
}

MapVar.Unlock() // lock end

ОБНОВЛЕНИЕ 1

Вот мой ответ на ваш аргумент ниже:

Этоцикл for занимает много времени, в этом цикле много вещей, поэтому блокировка замедлит другие процедуры

Согласно вашему утверждению The function "MyFunc" is run in a go routine, only once, there is no multiple runs of this func, тогда я думаю, что MyFunc будетВыполнение в виде goroutine - плохой выбор.

А для повышения производительности лучше сделать процесс внутри цикла для выполнения в goroutine.

func MyFunc() {
    for _, a := range MapVar.MyMap {
        go func(a MyDatas) {
           // do stuff here
        }(a)
    }
}

main() {
    MyFunc() // remove the go keyword
}

UPDATE 2

Если вы действительно хотите скопировать MapVar.MyMap в другой объект, передача его в другую переменную не решит, что (map отличается от типа int, float32 или другой тип ).

Пожалуйста, обратитесь к этой теме Как скопировать карту?

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