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.

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

报告相同问题?

悬赏问题

  • ¥30 python代码,帮调试
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条