首頁  >  文章  >  後端開發  >  如何優雅地停止 Go 例程:避免死鎖和無回應進程的指南?

如何優雅地停止 Go 例程:避免死鎖和無回應進程的指南?

Linda Hamilton
Linda Hamilton原創
2024-10-28 14:11:02535瀏覽

 How to Gracefully Stop a Go Routine: A Guide to Avoiding Deadlocks and Unresponsive Processes?

如何優雅地停止Go 例程

在Go 中,goroutines 提供輕量級並發,但優雅地終止它們可能具有挑戰性。這個問題解決了向 Goroutine 發送信號以停止其執行的需要。

提供的程式碼示範了透過將布林標誌 (tooLate) 設為 true 來嘗試停止 Goroutine。然而,這種方法是有問題的,因為從通道讀取資料會阻塞 goroutine。

解決方案 1:使用附加通道

此解決方案涉及使用第二個通道(太晚了)傳達停止訊號。即使 goroutine 沒有主動讀取該通道,該通道仍保持開啟。

<code class="go">func main() {
    tooLate := make(chan struct{}) // Unbuffered channel for stop signal
    proCh := make(chan string)

    go func() {
        for {
            fmt.Println("working")
            time.Sleep(1 * time.Second)
            select {
            case <-tooLate:
                fmt.Println("stopped")
                return
            case proCh <- "processed": // Non-blocking send
            default: // Allows the goroutine to continue without blocking
            }
            fmt.Println("done here")
        }
    }()

    select {
    case proc := <-proCh:
        fmt.Println(proc)
    case <-time.After(1 * time.Second):
        fmt.Println("too late")
        close(tooLate) // Signal to goroutine to stop
    }

    time.Sleep(4 * time.Second)
    fmt.Println("finish\n")
}</code>

在此解決方案中,當時間限製到期時,tooLate 通道將關閉,這會導致 goroutine 退出其阻塞 select 語句並返回。

解決方案 2:使用sync.Cond

或者,您可以使用sync.Cond 類型來實現更複雜的訊號機制。下面是一個範例:

<code class="go">func main() {
    var stopped bool
    cond := sync.NewCond(new(sync.Mutex))

    go func() {
        for {
            cond.L.Lock()
            defer cond.L.Unlock()

            if stopped {
                fmt.Println("stopped")
                return
            }
            fmt.Println("working")
            cond.Wait() // Wait for the signal to stop
        }
    }()

    time.Sleep(1 * time.Second)
    cond.Signal() // Send the stop signal

    time.Sleep(4 * time.Second)
    fmt.Println("finish\n")
}</code>

透過這個方法,goroutine 會等待 cond.Wait() 方法,直到收到 cond.Signal() 的訊號。

以上是如何優雅地停止 Go 例程:避免死鎖和無回應進程的指南?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn