Go - 并发合并排序会挂起,除非在基本情况下有 fmt 调用

问题描述 投票:0回答:1

这是我对并发合并排序的尝试。我首先非并发地编写并测试了它,所以问题与合并排序逻辑无关,而是与我如何使用 goroutine/channels 有关。

当我运行该程序时,它挂起几秒钟,然后收到信号:killed。

package main
import (
  "fmt"
)

func merge(a []int, b []int) []int {
  var aCounter int = 0
  var bCounter int = 0

  var newArray []int = []int{}
  
  for aCounter < len(a) || bCounter < len(b) {
    if aCounter >= len(a) {
      newArray = append(newArray, b[bCounter])
      bCounter++
    } else if bCounter >= len(b) {
      newArray = append(newArray, a[aCounter])
      aCounter++
    } else {
      if a[aCounter] < b[bCounter] {
        newArray = append(newArray, a[aCounter])
        aCounter++
      } else {
        newArray = append(newArray, b[bCounter])
        bCounter++
      }
    }
  }

  return newArray
}

func mergeSort(arr []int, c chan []int) {
  if len(arr) == 1 {
    c <- arr
  }

  firstHalfChan := make(chan []int)
  secondHalfChan := make(chan []int)
  
  go mergeSort(arr[0:len(arr)/2], firstHalfChan)
  go mergeSort(arr[len(arr)/2:len(arr)], secondHalfChan)

  firstHalf, secondHalf := <-firstHalfChan, <-secondHalfChan

  c <- merge(firstHalf, secondHalf)
}

func main() {
  s := []int{10, 3, 8, 1, 2, 9}

  channel := make(chan []int)
  go mergeSort(s, channel)

  sorted := <- channel

  fmt.Println(sorted)
}

但是,如果我向 mergeSort 的基本情况添加 fmt 调用,它实际上会打印所有预期值,然后打印合并排序的正确结果,并无错误地退出。

func mergeSort(arr []int, c chan []int) {
  if len(arr) == 1 {
    fmt.Println(arr) // ADDED
    
    c <- arr
  }

  firstHalfChan := make(chan []int)
  secondHalfChan := make(chan []int)
  
  go mergeSort(arr[0:len(arr)/2], firstHalfChan)
  go mergeSort(arr[len(arr)/2:len(arr)], secondHalfChan)

  firstHalf, secondHalf := <-firstHalfChan, <-secondHalfChan

  c <- merge(firstHalf, secondHalf)
}

任何人都可以解释这种行为吗?如果我做错了什么,请解释一下是什么?

go channel goroutine
1个回答
0
投票

问题是,当我将代码更改为使用通道而不是返回值时,我忽略了它现在会执行发送到通道的代码,这与返回语句不同,它会在函数中的该点之后停止代码执行.

修复方法是添加一个返回到基本情况:

  if len(arr) == 1 {
    c <- arr
    return
  }

fmt 语句“起作用”,因为它在无休止地生成更多 goroutine 之前为此调用添加了延迟,从而允许主线程在内存耗尽之前获取其结果并终止。

© www.soinside.com 2019 - 2024. All rights reserved.