繁体   English   中英

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

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

我运行的程序:

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 是此存储库的一部分以供参考,代码也可在同一存储库中找到。

我的问题是:函数onetwothree中的 time.Sleep() 应该被阻塞,直到睡眠持续时间,然后从通道中消耗字符串,但观察到睡眠对 goroutines 没有任何影响.

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

您似乎错过了本机持续时间标志类型: https : //pkg.go.dev/flag#DurationVar

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

同一程序的工作副本

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