当使用通过另一个goroutine的频道收到的数据同时启动多个goroutine来反转链接列表时,我遇到了一个奇怪的问题,这让我困扰了很多天,我只是想将列表拆分成几个没有断开链接的子列表然后分别启动goroutine来反转它,但我总是得到运行时错误,因为下面输出显示运行代码时,我真的不知道如何修复它后我尝试了很多更改但仍然得到相同的错误,有人可以指出问题还是给我建议?欢迎和赞赏您提供的任何帮助,如果您能提供改进的代码,那将是件好事,谢谢!
更新:问题是由数据争用造成的内存损坏引起的,它已经通过使用读写锁解决了!
这是我的代码:
package main
import "sync"
type node struct {
data int
next *node
}
type LinkedList struct {
head *node
size int
}
type splitResult struct {
beforeHead, head, tail *node
}
func splitList(head *node, sizoflst, sizofsublst int) <-chan *splitResult {
nGoroutines := sizoflst / sizofsublst
if sizoflst < sizofsublst {
nGoroutines++
} else {
if (sizoflst % sizofsublst) >= 6 {
nGoroutines++
}
}
ch := make(chan *splitResult, nGoroutines)
go func() {
defer close(ch)
var beforeHead *node
tail := head
ct := 0
for i := 0; i < nGoroutines; i++ {
for ct < sizofsublst-1 && tail.next != nil {
tail = tail.next
ct++
}
if i == nGoroutines-1 {
testTail := tail
for testTail.next != nil {
testTail = testTail.next
}
ch <- &splitResult{beforeHead, head, testTail}
break
}
ch <- &splitResult{beforeHead, head, tail}
beforeHead = tail
head = tail.next
tail = head
ct = 0
}
}()
return ch
}
func reverse(split *splitResult, ln **node, wg *sync.WaitGroup) {
defer wg.Done()
move := split.head
prev := split.beforeHead
if split.tail.next == nil {
*ln = split.tail
}
for move != split.tail.next {
temp := move.next
move.next = prev
prev = move
move = temp
}
}
func (ll *LinkedList) Reverse(sizofsublst int) {
var lastNode *node
var wg sync.WaitGroup
if ll.head == nil || ll.head.next == nil {
return
}
splitCh := splitList(ll.head, ll.size, sizofsublst)
for split := range splitCh {
wg.Add(1)
go reverse(split, &lastNode, &wg)
}
wg.Wait()
ll.head = lastNode
}
func (ll *LinkedList) Insert(data int) {
newNode := new(node)
newNode.data = data
newNode.next = ll.head
ll.head = newNode
ll.size++
}
func main() {
ll := &LinkedList{}
sli := []int{19, 30, 7, 23, 24, 0, 12, 28, 3, 11, 18, 1, 31, 14, 21, 2, 9, 16, 4, 26, 10, 25}
for _, v := range sli {
ll.Insert(v)
}
ll.Reverse(8)
}
输出:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x458db5]
goroutine 21 [running]:
main.reverse(0xc4200820a0, 0xc420096000, 0xc420098000)
/home/user/go/src/local/stackoverflow/tmp.go:69 +0x75
created by main.(*LinkedList).Reverse
/home/user/go/src/local/stackoverflow/tmp.go:85 +0x104