I try use "sync.mutex" protect my func,but i found that the lock still uses the caller to destroy it.
var mutex sync.mutex
This is error:
//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()
}
this is success,but destroyed my encapsulation method:
//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()
}
Thanks
The Go Programming Language Specification
An identifier may be exported to permit access to it from another package. An identifier is exported if both:
- the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and
- the identifier is declared in the package block or it is a field name or method name.
All other identifiers are not exported.
Put the function in its own package and don't export the mutex. For example.
package b
import (
"fmt"
"sync"
)
var mutex sync.Mutex
func B(i int) {
mutex.Lock()
fmt.Println(i)
mutex.Unlock()
}
To use,
package a
import "b"
func a() {
for i := 0; i < 10; i++ {
go b.B(i)
}
}
In the first example, all the calls to go b(i)
are called in a
's loop, but the loop can be finished before any of the goroutines have a chance to start, so if main returns, then all those goroutines stop.
In the second example, the mutex locks and doesn't unlock until Unlock
is called in each of the b
goroutines. The result is that the calls are completely sequential since each iteration of the loop in a
can't start until the last iteration's b
goroutine finishes and calls Unlock
.
A better practice in Go would be for your b function to take in a pointer to the mutex along with the number passed in, so in your original example it would look like:
//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()
}
Which would remove reliance on a global variable and also guarantee that all calls to b
are using the exact same mutex since we pass in a pointer to one mutex