如果信号量阻塞时间过长,则打印邮件,但在打印邮件时不要取消阻止呼叫者



我在Go中使用信号量库作为示例有以下代码:

package main
import (
    "fmt"
    "context"
    "time"
    "golang.org/x/sync/semaphore"
)
// This protects the lockedVar variable
var lock *semaphore.Weighted
// Only one go routine should be able to access this at once
var lockedVar string
func acquireLock() {
    err := lock.Acquire(context.TODO(), 1)
    if err != nil {
        panic(err)
    }
}
func releaseLock() {
    lock.Release(1)
}
func useLockedVar() {
    acquireLock()
    fmt.Printf("lockedVar used: %sn", lockedVar)
    releaseLock()
}
func causeDeadLock() {
    acquireLock()
    // calling this from a function that's already
    // locked the lockedVar should cause a deadlock.
    useLockedVar()
    releaseLock()
}
func main() {
    lock = semaphore.NewWeighted(1)
    lockedVar = "this is the locked var"
    // this is only on a separate goroutine so that the standard
    // go "deadlock" message doesn't print out.
    go causeDeadLock()
    // Keep the primary goroutine active.
    for true {
        time.Sleep(time.Second)
    }
}

有没有一种方法可以让acquireLock()函数调用在超时后打印一条消息,指示存在潜在的死锁,但不取消阻止调用?我希望死锁持续存在,但在达到超时时会写入日志消息。所以TryAcquire并不是我想要的。

我想要的psuedo代码示例:

afterFiveSeconds := func() {
    fmt.Printf("there is a potential deadlockn")
}
lock.Acquire(context.TODO(), 1, afterFiveSeconds)

如果Acquire调用被阻止超过5秒,则本例中的lock.Acquire调用将调用afterFiveSeconds回调,但不会解除对调用方的阻止。它将继续阻塞。

我想我已经找到了解决问题的方法。

func acquireLock() {
    timeoutChan := make(chan bool)
    go func() {
        select {
        case <-time.After(time.Second * time.Duration(5)):
            fmt.Printf("potential deadlock while acquiring semaphoren")
        case <-timeoutChan:
            break
        }
    }()
    err := lock.Acquire(context.TODO(), 1)
    close(timeoutChan)
    if err != nil {
        panic(err)
    }
}

最新更新