golang小白一枚,正在不断学习积累知识,现将学习到的知识记录一下,也是将我的所得分享给大家!而今天这篇文章《与列表的数据竞争。使用互斥锁进行列表并发访问》带大家来了解一下##content_title##,希望对大家的知识积累有所帮助,从而弥补自己的不足,助力实战开发!
问题内容
我正在进行数据竞赛,但我不太明白为什么。使用 -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()
并且在另一个 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()
解决方案
语句 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{}
}