为什么即使在运行time.Sleep的情况下,goroutine也不运行?

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

采用这段代码:

package main

import (
    "fmt"
    "time"
)

func main() {
    var x int
    go func() {
        for {
            x++
        }
    }()
    time.Sleep(time.Second)
    fmt.Println("x =", x)
}

为什么x最后等于0?我知道Go的调度程序需要time.Sleep()调用才能提取goroutine,但为什么不这样做呢?

Hint:在for循环中放置time.Sleep()或对runtime.Gosched()的调用可修复此代码。但是为什么呢?

更新:检查以下版本的相同代码:

package main

import (
    "fmt"
    "time"
)

func main() {
    var x int
    go func() {
        for i := 0; i < 10000; i++ {
            x++
        }
    }()
    time.Sleep(time.Second)
    fmt.Println("x =", x)
}

奇怪的是,现在执行了goroutine中的代码,并且x不再为0。编译器在此进行任何优化吗?

go goroutine go-scheduler
1个回答
1
投票

这是一个通用的多处理问题,不只适用于goroutine或Go。

无法保证代码中语句的执行顺序。例如,以下顺序是可能的(假设“ G”是您的goroutine,而“ M”是main中的代码):

  1. M:定义为x
  2. M:G定义并调用
  3. M:Sleep被叫
  4. M:Sleep完成
  5. M:Printlnx = 0
  6. G:x++
  7. G:x++
  8. ...(一些次数,甚至是0)
  9. 程序结束

观察一些交错尝试:

package main

import (
    "fmt"
    "time"
)

func main() {
    var x int

    go func() {
        for {
            time.Sleep(time.Second) 
            x++
        }
    }()
    time.Sleep(5*time.Second)
    fmt.Println("x =", x)
}

但是,仍然没有保证。要获得任何保证,请使用任何同步技术,例如频道。

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