dony113407 2013-06-07 15:20
浏览 70
已采纳

Go中并行Quicksort的死锁

As an exercise I'm trying to implement a parallel version of quicksort in Go. This is what I have so far:

func quicksort(nums []int, ch chan int, level int, threads int)  {
  level *= 2;
  if len(nums) == 1 {  ch<- nums[0]; close(ch); return }

  less := make([]int, 0)
  greater := make([]int,0)
  pivot := nums[0]
  nums = nums[1:]

  for _,i := range nums{
    switch{
    case i <= pivot:
      less = append(less,i)
    case i > pivot:
      greater = append(greater,i)
    }
  }

  ch1 := make(chan int, len(less))
  ch2 := make(chan int, len(greater))
  if(level <= threads){
    go quicksort(less, ch1, level, threads)
    go quicksort(greater,ch2, level, threads)
  }else{
    quicksort(less,ch1, level, threads)
    quicksort(greater,ch2, level, threads)
  }

  for i := range ch1{
    ch<-i;
  }
  ch<-pivot
  for i := range ch2{
    ch<-i;
  }
  close(ch)
  return
}

However, when I run it, I get an error claiming the program has deadlocked! I'm pretty stumped to what is causing this...

Thanks in advance,

Linus

  • 写回答

1条回答 默认 最新

  • dphphvs496524 2013-06-07 19:26
    关注

    The code has one problem, and at least one potential buggy usage case:

    1. It is missing a base case. Consider what happens if quicksort is asked to sort the empty slice.
    2. When calling quicksort for the first time, say in a main(), if you don't spawn the sorter in a separate goroutine, the main thread, running the toplevel sort, can block trying to write back to the channel (depending if the toplevel channel itself is buffered).

    For example:

    func main() {
        x := []int{3, 1, 4, 1, 5, 9, 2, 6}
        ch := make(chan int)
        quicksort(x, ch, 0, 0)    // buggy!
        for v := range(ch) {
            fmt.Println(v)
        }
    }
    

    This is buggy because this asks the main thread to do the sort, but it will inevitably block at this part of quicksort: it can't communicate with itself!

    for i := range ch1{
        ch<-i;
    }
    

    and it's at the write to the toplevel channel here that the main thread will deadlock.

    Contrast this with what happens if we do create a goroutine at toplevel:

    func main() {
        x := []int{3, 1, 4, 1, 5, 9, 2, 6}
        ch := make(chan int)
        go quicksort(x, ch, 0, 0)
        for v := range(ch) {
            fmt.Println(v)
        }
    }
    

    and now we avoid that particular deadlock problem.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求lingo代码和思路
  • ¥15 公交车和无人机协同运输
  • ¥15 stm32代码移植没反应
  • ¥15 matlab基于pde算法图像修复,为什么只能对示例图像有效
  • ¥100 连续两帧图像高速减法
  • ¥15 如何绘制动力学系统的相图
  • ¥15 对接wps接口实现获取元数据
  • ¥20 给自己本科IT专业毕业的妹m找个实习工作
  • ¥15 用友U8:向一个无法连接的网络尝试了一个套接字操作,如何解决?
  • ¥30 我的代码按理说完成了模型的搭建、训练、验证测试等工作(标签-网络|关键词-变化检测)