Goroutine запущен, но не выполнен или частично выполнен, даже если для синхронизации используется WaitGroup - PullRequest
0 голосов
/ 25 мая 2018

Я столкнулся со странной проблемой, когда использовал данные, полученные по каналу от другой программы, чтобы запустить несколько программ для одновременного обращения к связанному списку, что беспокоило меня в течение многих дней, я просто хочу разделить список на пару подсписков без разрыва связии затем соответственно запускаю 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 голосов
/ 27 мая 2018

Я думаю, что ваша проблема - просто присвоить значение Nil.Не назначайте нулевой указатель в каждом месте.

Код здесь

...