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

如何两次解锁互斥体

如何两次解锁互斥体

Go
MMTTMM 2023-07-17 15:25:08
两次解锁互斥体是否安全?我的代码:var m sync.RWMutex = sync.RWMutex{}func Read() {    m.RLock()    defer m.RUnlock()    // Do something that needs lock    err := SomeFunction1()    if err != nil {        return    }    m.RUnlock()    // Do something that does not need lock    SomeFunction2()}我需要defer m.RUnlock()案例SomeFunction1()返回错误。但是当SomeFunction1()返回没有错误时,m会被m.RUnlock()和解锁两次defer m.RUnlock()。两次解锁互斥体是否安全?如果没有,我应该如何修复我的代码?
查看完整描述

3 回答

?
繁花如伊

TA贡献2012条经验 获得超12个赞

两次解锁互斥体是否安全?

不,你不应该两次解锁互斥体。根据文档,这是一个运行时错误

RUnlock 撤消单个 RLock 调用;它不会影响其他同时阅读的读者。如果 rw 在进入 RUnlock 时未锁定以进行读取,则这是一个运行时错误。


如果没有,我应该如何修复我的代码?

我建议保留defer但仅m.RUnlock()在发生错误时才保留。如果您在SomeFunction1()和之间添加更多函数调用,这可以轻松扩展SomeFunction2()

func Read() {

    var err error

    m.RLock()

    defer func() {

        if err != nil {

            m.RUnlock()

        }

    }()

    


    // Do something that needs lock

    err = SomeFunction1()

    if err != nil {

        return

    }


    m.RUnlock()


    // Do something that does not need lock

    SomeFunction2()

}

在Go Playground上试试吧!



查看完整回答
反对 回复 2023-07-17
?
子衿沉夜

TA贡献1828条经验 获得超3个赞

解锁未锁定的互斥锁会导致恐慌。


您可以简单地删除defer并将其添加到 if 条件中:


var m sync.RWMutex = sync.RWMutex{}


func Read() {

    m.RLock()


    // Do something that needs lock

    err := SomeFunction1()

    if (err != nil) {

        m.RUnlock()

        return

    }


    m.RUnlock()


    // Do something that does not need lock

    SomeFunction2()

}

或者甚至更好(对可读性影响较小):


func Read() {

    m.RLock()


    err := SomeFunction1()

    m.RUnlock()

    if (err != nil) {

        return

    }


    SomeFunction2()

}


查看完整回答
反对 回复 2023-07-17
?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

来自戈多克:


如果 m 在进入 Unlock 时未锁定,则会发生运行时错误。


所以,不要这样做。


最简单的解决方法是不使用延迟解锁,而是在每个可能的出口处解锁。或者,你也可以这样做,但不太容易阅读:


func Read() {

    if err := func() {

      m.RLock()

      defer m.RUnlock()


      // Do something that needs lock

      err := SomeFunction1()

      if err != nil {

          return err

      }(); err != nil {

        return err

     }


    // Do something that does not need lock

    SomeFunction2()


}


查看完整回答
反对 回复 2023-07-17
  • 3 回答
  • 0 关注
  • 116 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信