Goroutine启动但未执行或部分执行,即使使用WaitGroup同步

时间:2018-05-25 08:32:08

标签: go synchronization channel goroutine

当使用通过另一个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

1 个答案:

答案 0 :(得分:0)

我认为你的问题只是为Nil分配一个值。不要在每个地方分配一个Nil指针。

Code Here