我尝试使用“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()
}
由于
答案 0 :(得分:1)
The Go Programming Language Specification
可以导出标识符以允许从另一个标识符访问它 包。如果两者都导出标识符:
- 标识符名称的第一个字符是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
的所有调用都使用完全相同的互斥锁,因为我们传入指向一个互斥锁的指针