代码之家  ›  专栏  ›  技术社区  ›  Alwin Doss

为什么goroutine不阻塞时间。睡眠(持续时间)

  •  0
  • Alwin Doss  · 技术社区  · 3 年前

    我运行的程序:

    package main
    
    import (
        "flag"
        "fmt"
        "os"
        "os/signal"
        "time"
    )
    
    var sleepSeconds string
    var timeToSleep time.Duration
    
    func init() {
        flag.StringVar(&sleepSeconds, "sleep", "1s", "-sleep \"3s\"")
    }
    
    func main() {
        startTime := time.Now()
        fmt.Println("Start Time: ", startTime)
        c := make(chan os.Signal)
        signal.Notify(c, os.Interrupt)
    
        // Block until a signal is received.
        flag.Parse()
        timeToSleep, err := time.ParseDuration(sleepSeconds)
        if err != nil {
            fmt.Println("unable to parse the duration: ", err)
            return
        }
        fmt.Println("Time to Sleep: ", timeToSleep)
    
        myChan := make(chan string)
        go one(myChan)
        go two(myChan)
        go three(myChan)
        var s os.Signal
        fmt.Println("Signal is, ", s)
        go func() {
            s = <-c
            fmt.Println("After receiving Signal is, ", s)
    
        }()
        i := 0
        for {
            i++
            generatedString := fmt.Sprintf("%d", i)
            fmt.Println("Generating... ", generatedString)
            myChan <- generatedString
            //      time.Sleep(timeToSleep)
            fmt.Println("Length of Channel: ", len(myChan))
            if s != nil {
                break
            }
        }
        fmt.Println("Total time the program ran for: ", time.Since(startTime))
    }
    
    func one(dataCh chan string) {
        for val := range dataCh {
            fmt.Printf("Value received in func one: %s\n", val)
            time.Sleep(timeToSleep)
        }
    }
    
    func two(dataCh chan string) {
        for val := range dataCh {
            fmt.Printf("Value received in func two: %s\n", val)
            time.Sleep(timeToSleep)
        }
    }
    
    func three(dataCh chan string) {
        for val := range dataCh {
            fmt.Printf("Value received in func three: %s\n", val)
            time.Sleep(timeToSleep)
        }
    }
    

    当我使用以下标志(5s)运行此程序时

    ./ichan -sleep "5s" > data.txt

    2.31606525s 但所有3个goroutine都应该被阻止,每次至少5秒。 data.txt是其中的一部分 repository 为了便于参考,同一存储库中也提供了代码。

    我的问题是: 函数中的time.Sleep() one , two three 它们应该在睡眠期间被阻塞,然后消耗通道中的字符串,但是观察到睡眠对goroutines没有任何影响。

    2 回复  |  直到 3 年前
        1
  •  2
  •   Peter saif iqbal    3 年前

    timeToSleep, err := 创建名为timeToSleep的新局部变量,该变量独立于具有相同名称的包级别变量,因此包级别变量始终为零。

    https://pkg.go.dev/flag#DurationVar

    func init() {
        flag.DurationVar(&timeToSleep, "sleep", 1*time.Second, `-sleep "3s"`)
    }
    
        2
  •  0
  •   Alwin Doss    3 年前

    同一程序的工作副本

    package main
    
    import (
        "flag"
        "fmt"
        "os"
        "os/signal"
        "time"
    )
    
    var sleepSeconds string
    var timeToSleep time.Duration
    var err error
    
    func init() {
        flag.StringVar(&sleepSeconds, "sleep", "1s", "-sleep \"3s\"")
    }
    
    func main() {
        startTime := time.Now()
        fmt.Println("Start Time: ", startTime)
        c := make(chan os.Signal)
        signal.Notify(c, os.Interrupt)
    
        // Block until a signal is received.
        flag.Parse()
        timeToSleep, err = time.ParseDuration(sleepSeconds)
        if err != nil {
            fmt.Println("unable to parse the duration: ", err)
            return
        }
        fmt.Println("Time to Sleep: ", timeToSleep)
    
        myChan := make(chan string)
        go one(myChan)
        go two(myChan)
        go three(myChan)
        var s os.Signal
        fmt.Println("Signal is, ", s)
        go func() {
            s = <-c
            fmt.Println("After receiving Signal is, ", s)
    
        }()
        i := 0
        for {
            i++
            generatedString := fmt.Sprintf("%d", i)
            fmt.Println("Generating... ", generatedString)
            myChan <- generatedString
            //      time.Sleep(timeToSleep)
            fmt.Println("Length of Channel: ", len(myChan))
            if s != nil {
                break
            }
        }
        fmt.Println("Total time the program ran for: ", time.Since(startTime))
    }
    
    func one(dataCh chan string) {
        for val := range dataCh {
            fmt.Printf("Value received in func one: %s\n", val)
            time.Sleep(timeToSleep)
        }
    }
    
    func two(dataCh chan string) {
        for val := range dataCh {
            fmt.Printf("Value received in func two: %s\n", val)
            time.Sleep(timeToSleep)
        }
    }
    
    func three(dataCh chan string) {
        for val := range dataCh {
            fmt.Printf("Value received in func three: %s\n", val)
            time.Sleep(timeToSleep)
        }
    }