在golang中,如何保护自己的锁安全不被调用者破坏?

时间:2017-11-18 18:10:23

标签: go

我尝试使用“sync.mutex”保护我的func,但我发现锁仍然使用调用者来销毁它。

var mutex sync.mutex

这是错误:

//caller use
func a() {
    for i := 0; i < 10; i++ {
        go b(i)
    }
}

//My func
func b(i int) {
    mutex.Lock()
    fmt.Println(i)
    mutex.Unlock()
}

这是成功的,但是破坏了我的封装方法:

//caller use
func a() {
    for i := 0; i < 10; i++ {
        mutex.Lock()
        go b(i)
    }
}

//my func
func b(i int) {
    fmt.Println(i)
    mutex.Unlock()
}

由于

2 个答案:

答案 0 :(得分:1)

  

The Go Programming Language Specification

     

Exported identifiers

     

可以导出标识符以允许从另一个标识符访问它   包。如果两者都导出标识符:

     
      
  • 标识符名称的第一个字符是Unicode大写字母(Unicode类“Lu”);和
  •   
  • 标识符在包块中声明,或者是字段名称或方法名称。
  •   
     

不会导出所有其他标识符。

将函数放在自己的包中,不要导出互斥锁。例如。

package b

import (
    "fmt"
    "sync"
)

var mutex sync.Mutex

func B(i int) {
    mutex.Lock()
    fmt.Println(i)
    mutex.Unlock()
}

使用,

package a

import "b"

func a() {
    for i := 0; i < 10; i++ {
        go b.B(i)
    }
}

答案 1 :(得分:0)

在第一个示例中,go b(i)的所有调用都在a的循环中调用,但循环可以在任何goroutine有机会启动之前完成,因此如果main返回然后所有那些goroutines停止。

在第二个示例中,在每个Unlock goroutine中调用b之前,互斥锁会锁定并且不会解锁。结果是调用是完全顺序的,因为a中的循环的每次迭代都不能开始,直到最后一次迭代的b goroutine完成并调用Unlock

Go中的一个更好的做法是让你的b函数接收指向互斥锁的指针以及传入的数字,所以在你原来的例子中它看起来像:

//caller use
func a() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            b(&mutex, i)
        }()
    }
    wg.Wait()
}

//My func
func b(mutex *sync.Mutex, i int) {
    mutex.Lock()
    fmt.Println(i)
    mutex.Unlock()
}

这将消除对全局变量的依赖,并且还保证对b的所有调用都使用完全相同的互斥锁,因为我们传入指向一个互斥锁的指针

相关问题