与列表进行数据竞争。使用互斥体列出并发访问

时间:2018-12-07 17:32:12

标签: go concurrency linked-list mutex goroutine

我正在一场数据竞赛中,我还不太清楚为什么。使用-race命令运行测试时,我已将其范围缩小到尝试在读取list.List时尝试访问它,但Mutexes似乎没有任何作用。

我在数组中有多个* list.list,像这样:

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()

在另一个goroutine中,还尝试读取并建立完整列表以返回

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 :(得分:1)

语句list := myListOfLists[someIndex]将数组元素复制到变量list。这将复制互斥锁,从而阻止互斥锁工作。 go vet命令报告此问题。

您可以通过使用指向数组元素的指针来避免复制:

list := &myListOfLists[someIndex]

另一种方法是使用指向MyList的指针数组。在使用它时,最好在MyList中使用列表值代替列表指针:

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

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