首页 > 解决方案 > 临时锁定资源,直到 goroutine 完成

问题描述

我有一个方法,它发送 HTTP 状态代码202 Accepted作为成功请求的指示符,并在其中运行另一个进程(goroutine)。像这样的东西:

return func(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusAccepted)
    go func() {
        time.Sleep(2 * time.Second)
    }()
}

我想暂时锁定资源以防止 goroutine 进程的多次执行。

return func(w http.ResponseWriter, r *http.Request) {
    c := make(chan bool)

    select {
    case _, unlocked := <-c:
        if unlocked {
            break
        }
    default:
        w.WriteHeader(http.StatusLocked)
        return
    }

    w.WriteHeader(http.StatusAccepted)
    go func(c chan bool) {
        time.Sleep(2 * time.Second)
        c <- true
    }(c)
}

我总是得到423 Locked状态码。我想,我还不了解频道。可以尝试使用互斥锁吗?

标签: restgogoroutine

解决方案


不是最好的解决方案,但它有效:

func (h *HookHandler) NewEvents() http.HandlerFunc {
    eventsLocker := struct {
        v   bool
        mux *sync.Mutex
    }{
        v:   true,
        mux: &sync.Mutex{},
    }

    return func(w http.ResponseWriter, r *http.Request) {
        if !eventsLocker.v {
            w.WriteHeader(http.StatusLocked)
            return
        }

        w.WriteHeader(http.StatusAccepted)

        go func() {
            defer eventsLocker.mux.Unlock()
            defer func() { eventsLocker.v = true }()

            eventsLocker.mux.Lock()
            eventsLocker.v = false

            time.Sleep(2 * time.Second)
        }()
    }
}

推荐阅读