go - 如何暂停和恢复goroutine?

标签 go concurrency channel goroutine

我正在尝试暂停并恢复常规。我知道我可以sleep运行,但是我在寻找的是按钮“暂停/恢复”而不是计时器。

这是我的尝试。我正在使用 channel 的阻止功能暂停,并使用select切换基于 channel 值执行的操作。但是,在我的情况下,输出始终为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是“慢”的以检查那些 channel ,则可以在pauseresume上都发送一个值(假设它们已缓冲),这样就可以准备从两个 channel 接收数据,可以先选择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

关于go - 如何暂停和恢复goroutine?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60489944/

相关文章:

go - Go bytes.Buffer 是线程安全的吗?

Go net/http 请求正文始终为 nil

c++ - 从 concurrent_unordered_map 中删除项目列表

javascript - 使用 Channel API 接收来自任务队列中任务的消息

api - GAE Java API channel

templates - Google Go 文本模板中范围最后一个元素的特殊情况处理

go - 无法将错误转换为 go-sqlite3.Error

c++ - 线程环基准

http - 去http.Get,并发, "Connection reset by peer"

并发模式帮助 - 扇入并返回结果?