如何暂停和恢复goroutine?

问题描述 投票:2回答:2

我正试图暂停并恢复日常工作。我知道我可以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{}
}
go concurrency channel goroutine
2个回答
1
投票

具有多个就绪案例的select,会随机选择一个伪随机数。因此,如果goroutine是“慢”的以检查那些通道,则可以在pauseresume上都发送一个值(假设它们已被缓冲),这样就可以准备从两个通道接收数据,并且可以先选择resume ,并且在以后的迭代中,[go]不应再暂停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

0
投票

您需要初始化通道,请记住,从零个通道读取的数据始终会阻塞。

带有select大小写的default永远不会阻塞。

这里是程序的修改版本,可解决上述问题:

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{}
}

© www.soinside.com 2019 - 2024. All rights reserved.