如何运行goroutine的单个实例
我有一个goroutine,将运行多次。但它一次只能运行一个(单个实例)。确保某个goroutine一次只能运行一个goroutine的正确/惯用方法是什么 下面是我精心设计的示例代码来说明这一点:如何运行goroutine的单个实例,go,thread-safety,goroutine,Go,Thread Safety,Goroutine,我有一个goroutine,将运行多次。但它一次只能运行一个(单个实例)。确保某个goroutine一次只能运行一个goroutine的正确/惯用方法是什么 下面是我精心设计的示例代码来说明这一点: func main() { // Contrived example!!!!!! // theCaller() may be run at multiple, unpredictable times // theJob() must only be run one at a
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的问题和其他评论,目标似乎是在作业尚未运行的情况下启动新作业 使用受保护的布尔变量来记录作业的运行状态。启动作业时将变量设置为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()
}
也可以使用较低级别的包,它可能比使用互斥锁具有更好的性能
var jobIsRunning uint32
func maybeStartJob() {
if atomic.CompareAndSwapUint32(&jobIsRunning, 0, 1) {
go func() {
theJob()
atomic.StoreUint32(&jobIsRunning, 0)
}()
}
}
sync/atomic包文档警告说,包中的函数需要非常小心才能正确使用,大多数应用程序都应该使用sync包 看看互斥体。牙床JimB我不知道单人飞行。我不得不研究一下,因为他们提供的例子似乎很复杂。然而,一个立即停止显示的是注释,该注释说“如果出现重复,重复调用方将等待//原始完成”。如果goroutine已经运行了,我只需要其他人说不要再尝试运行它。这对我来说确实有点像X-Y问题。。。为什么要使用例程,但强制它们按顺序运行(本质上是将并发进程转换为顺序进程?)。根据你在做什么,你可以很容易地使用一个频道,though@EliasVanOotegem我不想让它们按顺序运行。这意味着阻塞和排队。我希望以后尝试运行goroutine时,能够意识到它已经在运行,不需要做任何事情,然后继续运行。谢谢。我认为这不能满足我的需要,因为
jobisrunning mu.Lock()
块位于maybeStartJob()
。我不能阻止maybeStartJob()
,因为它是事件驱动的,不完全在我的控制之下。这就是我遇到的问题,因为sync
包中的几乎所有东西都是阻止调用。@ThunderCat如果你锁定了函数,你需要jobsrunning
标志吗?这个例子似乎有点过于复杂了。这样的事情不足以确保作业的内容一次只由一个goroutine执行,同时也允许它由多个goroutine并发“排队”吗@Michael,你能看看上面评论中的链接吗?这能解决你的问题吗?@Michael maybeStartJob在查看标志时会屏蔽。这不太可能是应用程序中的问题。