我有以下情况
wg.Add(1)
go func(wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case <-tickerCR.C:
_ = ProcessCommands()
case <-ow.quitCR:
logger.Debug("Stopping ProcessCommands goroutine")
return
}
}
}(&wg)
我能以某种方式确保如果ProcessCommands正在执行,则忽略下一个股票报价事件。基本上我想避免并行执行ProcessCommands
答案 0 :(得分:2)
您想要的东西称为互斥。可以通过Mutex来实现。
var m Mutex
func process() {
m.Lock()
defer m.Unlock()
ProcessCommands()
}
答案 1 :(得分:1)
您可以创建一个具有两个字段的类型,一个函数和一个互斥锁,当调用他的类型时,可以说运行方法,它锁定,推迟解锁并调用存储的函数。之后,您只需要使用所需的功能创建该类型的实例。 OOP进行救援。请记住,函数可以以与字符串相同的方式存储在结构中。
import (
"sync"
)
type ProtectedCaller struct {
m sync.Mutex
f func()
}
func (caller *ProtectedCaller) Call() {
caller.m.Lock()
defer caller.m.Unlock()
caller.f()
}
func ProtectCall(f func()) ProtectedCaller {
return ProtectedCaller{f: f}
}
var processCommands = ProtectCall(ProcessCommands)
答案 2 :(得分:0)
有一个半标准模块 x/sync/singleflight :
使用方法:
import "golang.org/x/sync/singleflight"
var requestGroup singleflight.Group
// This handler should call it's upstream only once:
http.HandleFunc("/singleflight", func(w http.ResponseWriter, r *http.Request) {
// define request group - each request can have it's specific ID
// singleflight ensures only 1 request with any given ID is processed at a time
// also you can have different IDs - to be processed simultaneously
// just set ID to "singleflight-1", "singleflight-2", etc
res, err, shared := requestGroup.Do("singleflight", func() (interface{}, error) {
fmt.Println("calling the endpoint")
response, err := http.Get("https://jsonplaceholder.typicode.com/photos")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return nil, err
}
responseData, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
time.Sleep(2 * time.Second)
return string(responseData), err
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
result := res.(string)
fmt.Println("shared = ", shared)
fmt.Fprintf(w, "%q", result)
})
答案 3 :(得分:0)
您可以使用sync.Once
并防止多次调用一个函数,如下所示:
wg.Add(1)
var once sync.Once
go func(wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case <-tickerCR.C:
// look at this line, "ProcessCommands" function will call only once
once.Do(ProcessCommands)
case <-ow.quitCR:
logger.Debug("Stopping ProcessCommands goroutine")
return
}
}
}(&wg)