为了账号安全,请及时绑定邮箱和手机立即绑定

Golang:互斥锁持有时间过长后出现恐慌

Golang:互斥锁持有时间过长后出现恐慌

Go
HUWWW 2022-01-10 10:26:15
我试图弄清楚是什么让我的程序挂起,我的大部分锁不应该超过 200 毫秒。(实际上要少得多!)我想创建两个新函数 (Lock()和Unlock()),以便 Lock 将有一个计时器,如果 Lock 已被持有超过 200 毫秒,该计时器将发生恐慌。这是我目前的尝试,但它不起作用,有什么提示吗?type ShardKV struct {  lockChan chan bool}func (kv *App) lock(reason string) {    kv.mu.Lock()    f := func () {        fmt.Println("PANIC: ms passed")        select {        case <- kv.lockChan:            //        default:            panic("PANIC: " + reason)        }  }    time.AfterFunc(time.Second * 10, f)}func (kv *App) unlock(reason string) {    kv.lockChan <- true    kv.mu.Unlock()}
查看完整描述

3 回答

?
森栏

TA贡献1810条经验 获得超5个赞

您需要使用的返回值time.AfterFunc。这是一个工作示例:


package main


import (

    "fmt"

    "sync"

    "time"

)


type Foo struct {

    m sync.Mutex

    timer *time.Timer

}


func (f *Foo) lock() {

    f.m.Lock()

    f.timer = time.AfterFunc(3 * time.Second, func() {

        panic("Too long!")

    })

}


func (f *Foo) unlock() {

    f.timer.Stop()

    f.m.Unlock()

}


func main() {

    foo := &Foo{

        sync.Mutex{},

        &time.Timer{},

    }


    foo.lock()


    // Uncomment this to see the difference

    //time.Sleep(5 * time.Second)


    foo.unlock()

    fmt.Println("Success!")

}

游乐场链接:https : //play.golang.org/p/WVPp0_Iqlb


查看完整回答
反对 回复 2022-01-10
?
隔江千里

TA贡献1906条经验 获得超10个赞

您说过如果锁定已保持 200 毫秒,您希望您的代码恐慌,但您给了计时器 10 秒的等待时间。这只会在恐慌之前等待 10 秒而不是 200 秒。我已经尝试过您的代码以下列方式对其进行编辑:


package main


import (

    "sync"

    "fmt"

    "time"

)



type App struct {

    mu sync.Mutex

    lockChan chan bool

}


func (kv *App) lock(reason string) {

    kv.mu.Lock()


    f := func () {

        fmt.Println("PANIC: ms passed")

        select {

        case <- kv.lockChan:

        //

        default:

            panic("PANIC: " + reason)

        }

    }

    time.AfterFunc(time.Millisecond * 200, f)

}


func (kv *App) unlock(reason string) {

    kv.lockChan <- true

    kv.mu.Unlock()

}


func NewApp() *App {

    app := App{}

    app.lockChan = make(chan bool)

    return &app

}


func main() {

    app := NewApp()

    app.lock("locking")

    time.Sleep(time.Millisecond * 300)


}

上面的代码工作得很好并且很恐慌。如果将 main 函数中的持续时间设置为200 * time.Millisecond,它不会恐慌并停止运行。


查看完整回答
反对 回复 2022-01-10
?
白衣非少年

TA贡献1155条经验 获得超0个赞

您的 lock 函数在调用包含 select 语句的 f 函数之前等待 10 秒,实现您想要做的更简单的方法可能是:


func (kv *App) lock(reason string) {

    kv.mu.Lock()

    select {

    case <- kv.lockChan:

        //

    case <-time.After(time.Second * 10):

        panic("PANIC: " + reason)

    }

}


查看完整回答
反对 回复 2022-01-10
  • 3 回答
  • 0 关注
  • 256 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号