登录
首页 >  Golang >  Go问答

运行唯一的goroutine

来源:stackoverflow

时间:2024-03-03 10:30:26 271浏览 收藏

本篇文章给大家分享《运行唯一的goroutine》,覆盖了Golang的常见基础知识,其实一个语言的全部知识点一篇文章是不可能说完的,但希望通过这些问题,让读者对自己的掌握程度有一定的认识(B 数),从而弥补自己的不足,更好的掌握它。

问题内容

我有一个将运行多次的 goroutine。但它一次只能运行一个(单个实例)。确保某个 goroutine 一次只能运行一个的正确/惯用方法是什么?

这是我设计的示例代码来说明这一点:

func main() {
    // Contrived example!!!!!!
    // theCaller() may be run at multiple, unpredictable times
    // theJob() must only be run one at a time
    go theCaller()
    go theCaller()
    go theCaller()
}

func theCaller() {
    if !jobIsRunning { // race condition here!
        jobIsRunning = true
        go theJob()
    }
}

var jobIsRunning bool

// Can run multiple times, but only one at a time
func theJob() {
    defer jobDone()
    do_something()
}

func jobDone() {
    jobIsRunning = false
}

解决方案


根据op的问题和其他评论,看起来目标是当且仅当作业尚未运行时才开始新作业。

使用受sync.Mutex保护的布尔变量来记录作业的运行状态。开始作业时将该变量设置为 true,作业完成时将该变量设置为 false。测试此变量以确定是否应启动作业。

var (
    jobisrunning   bool
    jobisrunningmu sync.mutex
)

func maybestartjob() {
    jobisrunningmu.lock()
    start := !jobisrunning
    jobisrunning = true
    jobisrunningmu.unlock()
    if start {
        go func() {
            thejob()
            jobisrunningmu.lock()
            jobisrunning = false
            jobisrunningmu.unlock()
        }()
    }
}

func main() {
    maybestartjob()
    maybestartjob()
    maybestartjob()
}

也可以使用较低级别的 sync/atomic 包,并且可能比使用互斥体具有更好的性能。

var jobIsRunning uint32

func maybeStartJob() {
    if atomic.CompareAndSwapUint32(&jobIsRunning, 0, 1) {
        go func() {
            theJob()
            atomic.StoreUint32(&jobIsRunning, 0)
        }()
    }
}

sync/atomic 包文档警告说,包中的函数需要非常小心才能正确使用,并且大多数应用程序应该使用sync 包。

到这里,我们也就讲完了《运行唯一的goroutine》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>