簡體   English   中英

如何暫停和恢復 goroutine?

[英]How to pause and resume goroutine?

我正在嘗試暫停和恢復 groutine。 我知道我可以在跑步時sleep ,但我正在尋找就像一個“暫停/恢復”按鈕而不是一個計時器。

這是我的嘗試。 我正在使用通道的阻塞功能來暫停,並根據通道值select切換要執行的內容。 但是,輸出始終在我的情況下Running

func main() {
    ctx := wctx{}
    go func(ctx wctx) {
        for {
            time.Sleep(1 * time.Second)
            select {
            case <-ctx.pause:
                fmt.Print("Paused")
                <-ctx.pause
            case <-ctx.resume:
                fmt.Print("Resumed")
            default:
                fmt.Print("Running \n")
            }
        }
    }(ctx)

    ctx.pause <- struct{}{}
    ctx.resume <- struct{}{}
}

type wctx struct {
    pause  chan struct{}
    resume chan struct{}
}

一個select多准備的情況下選擇一個偽隨機。 因此,如果 goroutine 檢查這些通道很“慢”,您可能會在pauseresume發送一個值(假設它們已緩沖),以便從兩個通道接收可以准備好,並且可以首先選擇resume ,然后在以后的迭代中goroutine 不應再pause時的暫停。

為此,您應該使用由互斥鎖同步的“狀態”變量。 像這樣的東西:

const (
    StateRunning = iota
    StatePaused
)

type wctx struct {
    mu    sync.Mutex
    state int
}

func (w *wctx) SetState(state int) {
    w.mu.Lock()
    defer w.mu.Unlock()
    w.state = state
}

func (w *wctx) State() int {
    w.mu.Lock()
    defer w.mu.Unlock()
    return w.state
}

測試它:

ctx := &wctx{}
go func(ctx *wctx) {
    for {
        time.Sleep(1 * time.Millisecond)
        switch state := ctx.State(); state {
        case StatePaused:
            fmt.Println("Paused")
        default:
            fmt.Println("Running")
        }
    }
}(ctx)

time.Sleep(3 * time.Millisecond)
ctx.SetState(StatePaused)
time.Sleep(3 * time.Millisecond)
ctx.SetState(StateRunning)
time.Sleep(2 * time.Millisecond)

輸出(在Go Playground上試試):

Running
Running
Running
Paused
Paused
Paused
Running
Running

你需要初始化你的通道,記住從 nil 通道讀取總是阻塞的。

default情況下的select永遠不會阻塞。

這是您的程序的修改版本,它解決了上述問題:

package main

import (
    "fmt"
    "time"
)

func main() {
    ctx := wctx{
        pause:  make(chan struct{}),
        resume: make(chan struct{}),
    }

    go func(ctx wctx) {
        for {
            select {
            case <-ctx.pause:
                fmt.Println("Paused")
            case <-ctx.resume:
                fmt.Println("Resumed")
            }

            fmt.Println("Running")
            time.Sleep(time.Second)
        }
    }(ctx)

    ctx.pause <- struct{}{}
    ctx.resume <- struct{}{}
}

type wctx struct {
    pause  chan struct{}
    resume chan struct{}
}

暫無
暫無

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

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