【问题标题】:Concurrent sort并发排序
【发布时间】:2022-01-27 14:52:06
【问题描述】:

我遇到了一个死锁错误,一直在敲我的头,任何帮助将不胜感激。下面是程序应该做的事情。我正在寻找关于它为什么会中断以及我是否可以改进我的思维过程的解释

" 编写程序对整数数组进行排序。该程序应将数组划分为 4 个部分, 每个都由不同的 goroutine 排序。每个分区的大小应大致相等。然后主 goroutine 应该将 4 个排序的子数组合并为一个大的排序数组。

程序应该提示用户输入一系列整数。每个 goroutine 排序数组的 ¼ 应该打印它将排序的子数组。排序完成后,主 goroutine 应该打印整个排序列表。 "


package main

import (
    "bufio"
    "fmt"
    "math"
    "os"
    "sort"
    "strconv"
    "strings"
    "sync"
)

func splitAndSortList(intList []int, chunkSize float64, chunkLength int, i int, wg sync.WaitGroup, c chan []int) {
    listN := intList[i*chunkLength : (i*chunkLength)+chunkLength]
    sort.Ints(listN)
    c <- listN
    fmt.Println("Sorted Chunk: n -", i, " List", listN)
    wg.Done()
}

func stringToInt(strList string, chunkSize float64) []int {
    var intList []int
    for _, s := range strings.Fields(strList) {
        i, err := strconv.Atoi(s)
        if err == nil {
            intList = append(intList, i)
        }
    }
    return intList
}

func main() {
    fmt.Println("Enter a sequence of integers: ")
    reader := bufio.NewReader(os.Stdin)
    numList, _ := reader.ReadString('\n')

    chunkSize := 4.0
    intList := stringToInt(numList, chunkSize)
    floatListLen := float64(len(intList))
    chunkLength := int(math.Ceil(float64(floatListLen / chunkSize)))

    c := make(chan []int, chunkLength)
    semiSortedList := []int{}

    var wg sync.WaitGroup

    for i := 0; i < int(chunkSize); i++ {
        wg.Add(1)
        go splitAndSortList(intList, chunkSize, chunkLength, i, wg, c)
    }
    wg.Wait()
    close(c)
    for l := range c {
        semiSortedList = append(semiSortedList, l...)
    }

    fmt.Println("after sort", semiSortedList)
    fmt.Println("Sorting Complete")
}

【问题讨论】:

  • 您不得复制文档中明确说明的 sync.WaitGroup。

标签: arrays sorting go concurrency


【解决方案1】:

代码中有两个错误。

  1. chunkLength 小于 chunkSize。因此,您将阻止 c &lt;- listN 的 splitAndSortList 函数内部,并且它永远不会调用 wg.Done()。
    c := make(chan []int, chunkLength)

    for i := 0; i < int(chunkSize); i++ {
  1. 您不能通过值传递sync.WaitGroup。因为你会得到它的副本,然后在副本上调用 wg.Done()。原来的等待组将永远阻塞。 func splitAndSortList(wg *sync.WaitGroup)

这是工作代码:

package main

import (
    "bufio"
    "fmt"
    "math"
    "os"
    "sort"
    "strconv"
    "strings"
    "sync"
)

func splitAndSortList(intList []int, chunkSize float64, chunkLength int, i int, wg *sync.WaitGroup, c chan []int) {
    listN := intList[i*chunkLength : (i*chunkLength)+chunkLength]
    sort.Ints(listN)
    c <- listN
    fmt.Println("Sorted Chunk: n -", i, " List", listN)
    wg.Done()
}

func stringToInt(strList string, chunkSize float64) []int {
    var intList []int
    for _, s := range strings.Fields(strList) {
        i, err := strconv.Atoi(s)
        if err == nil {
            intList = append(intList, i)
        }
    }
    return intList
}

func main() {
    fmt.Println("Enter a sequence of integers: ")
    reader := bufio.NewReader(os.Stdin)
    numList, _ := reader.ReadString('\n')

    chunkSize := 4.0
    intList := stringToInt(numList, chunkSize)
    floatListLen := float64(len(intList))
    chunkLength := int(math.Ceil(float64(floatListLen / chunkSize)))

    c := make(chan []int, int(chunkSize))
    semiSortedList := []int{}

    var wg sync.WaitGroup

    for i := 0; i < int(chunkSize); i++ {
        wg.Add(1)
        go splitAndSortList(intList, chunkSize, chunkLength, i, &wg, c)
    }
    wg.Wait()
    close(c)
    for l := range c {
        semiSortedList = append(semiSortedList, l...)
    }

    fmt.Println("after sort", semiSortedList)
    fmt.Println("Sorting Complete")
}

【讨论】:

  • “你不应该通过值传递sync.WaitGroup”。 N. 这不是“应该”,应该是“不得”。
  • 非常感谢各位,感谢您的解释 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-28
  • 1970-01-01
  • 2014-06-18
  • 2017-02-09
相关资源
最近更新 更多