Go defer unlock 总结

defer unlock 实际工作中经常遇到 Lock 后需要 Unlock 的情况,这里总结一下优化过程。

  1. 一般情况 假设想给某 map 变量加锁后使用
var mu sync.Mutex
var mVar map[int]int = make(map[int]int)

func func1(){
  mu.Lock()
  defer mu.Unlock()

  for k, v := range mVar {
    doSomeThing(k, v)
  }

  doSomeOthers()
}
  • 上面的处理缺点是doSomeOthers()调用时其实已经不需要 Lock 了,会阻塞其他携程
  1. 将 Unlock 提前
func func1(){
  mu.Lock()
  for k, v := range mVar {
    doSomeThing(k, v)
  }
  mu.Unlock()

  doSomeOthers()
}
  • Unlock()doSomeOthers()前执行,避免阻塞其他携程
  • 但是存在隐患:如果doSomeThing中发生 panic,并且在外层 recover 了,则会缺少 Unlock 而可能导致死锁
  1. 匿名函数 + defer
func func1(){

  func(){
    mu.Lock()
    defer mu.Unlock()
    for k, v := range mVar {
      doSomeThing(k, v)
    }
  }()

  doSomeOthers()
}
  • 匿名函数中使用 defer,保证doSomeThing发生 panic 也能正确 Unlock
  • 匿名函数立即执行,在执行doSomeOthers前就会 Unlocks