Гонка данных со списком. Список одновременного доступа с мьютексами - PullRequest
0 голосов
/ 07 декабря 2018

У меня гонка данных, и я не могу понять, почему.Выполняя мои тесты с помощью команды -race, я сузил его до попытки доступа к list.List во время чтения из него, но мои мьютексы, похоже, ничего не делают.

У меня есть ряд * list.Lists внутри массива примерно так:

type MyList struct {
    mutex sync.Mutex
    *list.List
}

type SomeObj struct {
    data string
}

var myListOfLists [10]MyList

Я читаю и пишу из списка примерно так:

list := myListOfLists[someIndex]
list.mutex.Lock()
for e := list.Front(); e != nil; e = e.Next() {
        if (...) {
            list.MoveToFront(e)
        }
}
list.mutex.Unlock()

и в другой программе также пытается прочитать и построить полный список для возврата

var fullCopy []*SomeObj
list := myListOfLists[someIndex]

list.mutex.Lock()
for e := list.Front(); e != nil; e = e.Next() {
        fullCopy = append(fullCopy, e.Value.(SomeObj))
}
list.mutex.Unlock()

1 Ответ

0 голосов
/ 07 декабря 2018

Оператор list := myListOfLists[someIndex] копирует элемент массива в переменную list.Это копирует мьютекс, тем самым предотвращая его работу.Команда go vet сообщает об этой проблеме.

Вы можете избежать копирования, используя указатель на элемент массива:

list := &myListOfLists[someIndex]

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

type MyList struct {
    mutex sync.Mutex
    list.List
}

var myListOfLists [10]*MyList
for i := range myListOfLists {
   myListOfLists[i] = &MyList{}
}
...