簡體   English   中英

如何運行goroutine的單個實例

[英]How to run single instance of goroutine

我有一個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()
}

也可以使用較低級別的同步/原子包,並且與使用互斥鎖相比,它可能具有更好的性能。

var jobIsRunning uint32

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

同步/原子軟件包的文檔警告說,軟件包中的功能需要格外小心才能正確使用,並且大多數應用程序應使用同步軟件包。

暫無
暫無

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

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