如何两次解锁互斥体

两次解锁互斥体是否安全?我的代码:


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()。


两次解锁互斥体是否安全?如果没有,我应该如何修复我的代码?


MMTTMM
浏览 117回答 3
3回答

繁花如伊

两次解锁互斥体是否安全?不,你不应该两次解锁互斥体。根据文档,这是一个运行时错误。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上试试吧!

子衿沉夜

解锁未锁定的互斥锁会导致恐慌。您可以简单地删除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()}

慕无忌1623718

来自戈多克:如果 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()}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go