简体   繁体   English

为什么 goroutine 不会阻塞 time.Sleep(duration)

[英]Why does the goroutine not block for time.Sleep(duration)

The program that I ran:我运行的程序:

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)
    }
}

When I run this program with the following flags(5s)当我使用以下标志(5s)运行此程序时

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

output is puzzling as I see the program has only run for 2.31606525s but all 3 goroutines are supposed to be blocked at least for 5 seconds each.输出令人费解,因为我看到程序只运行了2.31606525s但所有 3 个 goroutine 都应该被阻塞至少 5 秒。 data.txt is part of this repository for reference, code is also available in the same repository. data.txt 是此存储库的一部分以供参考,代码也可在同一存储库中找到。

My Question is: time.Sleep() in the functions one , two and three are supposed to be blocked until the duration of sleep and then consume the strings from the channel, but the observation is that sleep is not having any effect on the goroutines.我的问题是:函数onetwothree中的 time.Sleep() 应该被阻塞,直到睡眠持续时间,然后从通道中消耗字符串,但观察到睡眠对 goroutines 没有任何影响.

timeToSleep, err := creates a new, local variable named timeToSleep that is independent of the package level variable with the same name, so the package level variable is always zero. timeToSleep, err :=创建一个名为 timeToSleep 的新局部变量,该变量独立于同名的包级别变量,因此包级别变量始终为零。

It seems you have missed that there is a native duration flag type: https://pkg.go.dev/flag#DurationVar您似乎错过了本机持续时间标志类型: https : //pkg.go.dev/flag#DurationVar

func init() {
    flag.DurationVar(&timeToSleep, "sleep", 1*time.Second, `-sleep "3s"`)
}

Working Copy of the same program同一程序的工作副本

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)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM