去常规阻止其他人

时间:2013-07-30 17:13:53

标签: go channel goroutine

以下代码永远运行,而不是在开始后停止一秒。 带有无限循环的go例程似乎阻止了另一个发送到超时通道。这是正常的吗?

 func main(){
   timeout:=make(chan int)
   go func(){
      time.SLeep(time.Second)
      timeout<-1
    }()

    res:=make(chan int)
    go func(){
        for{
        }
        res<-1
    }()
    select{
        case<-timeout:
            fmt.Println("timeout")
        case<-res:
            fmt.Println("res")
    }
}

2 个答案:

答案 0 :(得分:3)

那是因为使用单个处理器,你的第二个goroutine将忙于等待(通过循环独占处理器,永远不让其他goroutine运行)。

如果你把一个time.Sleep(time.Millisecond)放在for循环中,它就可以了:

http://play.golang.org/p/M4jeckcmov

答案 1 :(得分:2)

简答:是的。

当前实现使用goroutines之间的协作调度。这意味着goroutine必须将执行交给调度程序以运行另一个goroutine。将来有希望使用不具有此限制的抢占式调度程序。

当发生以下任何情况时,Goroutines会向调度程序屈服(可能不是一个全面的列表):

  • unbuffered chan send / recv
  • 系统调用(包括文件/网络读写)
  • 内存分配
  • time.Sleep()被称为
  • runtime.Gosched()被称为

最后一个允许您在处理器密集型循环时手动屈服于调度程序。我从来没有找到它的需要因为几乎所有我使用的东西都有足够的通信(频道或系统io),我的程序永远不会卡住。

还有GOMAXPROCS,你可能会听到它作为解决方案。虽然它允许所有goroutine通过将它们放在不同的线程中来运行,但垃圾收集器最终会尝试运行并停止这个世界。当它停止世界时,不允许运行任何goroutine,如果高cpu goroutines永远不会产生,GC将永远阻止goroutines但永远不会运行。