簡體   English   中英

goroutines中的golang計時器阻止

[英]golang timer blocking in goroutines

下面的代碼來自示例-計時器

package main

import (
    "time"
    "fmt"
)

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    timer1 := time.NewTimer(time.Second * 1)

    <-timer1.C
    fmt.Println("Timer 1 expired")

    timer2 := time.NewTimer(300) //change the duration to be more shorter
    go func() {
        <-timer2.C
        fmt.Printf("Timer 2 expired")
    }()

    stop2 := timer2.Stop()
    if stop2 {
        fmt.Printf("Timer 2 stopped")
    }
}

如果我運行上面的代碼,輸出將是(結果一):

Timer 1 expired
Timer 2 stopped

但是如果我將匿名函數的主體更改為:

fmt.Printf("Timer 2 expired")
<-timer2.C

輸出仍然像以前一樣。 我很困惑,為什么第二個輸出不像(結果二):

Timer 1 expired
Timer 2 expired
Timer 2 stopped

根據我的理解, <-timer2.C阻塞goroutine的其余部分 ,直到計時器通道獲取值為止,因此,如果在<-timer2.C之后放置fmt.Printf(“ Timer 2 expired”) ,輸出將喜歡結果一,但是如果我將fmt.Printf(“ Timer 2 expired”)放在<-timer2.C之前,我認為打印操作將不會被阻止。

希望有人能幫幫我,謝謝大家。

問題可能出在打印語句和程序結尾之間沒有保證的“發生在……之前”的關系。 當主Goroutine退出時,整個程序退出。

Goroutine具有啟動時間,運行時具有何時切換到另一個正在運行的Goroutine的標准。 可能發生的情況是匿名函數中沒有代碼被執行,因為缺少任何阻塞操作(甚至是昂貴的函數調用)的主goroutine很快退出

更改GOMAXPROCS (如該程序嘗試執行的操作)有時可以“解決”該問題,因為多個線程有機會潛入某些代碼,因為它們不必依賴運行時的顯式上下文切換,但無需保證“先發生”關系,或者至少沒有任何聲明有意使主goroutine掛起一會兒(例如空的select{}for{}等),您實際上不能依賴主goroutine之外的任何代碼運行。

完全有可能在完全不同的計算機上(甚至在負載較小,或超頻或...的同一台計算機上),得到預期的行為。 不幸的是,由於您了解到,您無法依靠它,因此請確保同步您的goroutine。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM