Reputation: 469
I have a code snippet:
type calculation struct{
sum int
mutex sync.Mutex
}
func dosomething(c *calculation , wg *sync.WaitGroup) {
c.mutex.Lock()
c.sum++
c.mutex.Unlock()
wg.Done()
}
func main() {
t := time.Now()
c := new(calculation)
wg := new(sync.WaitGroup)
for i:=0; i<10000000; i++{
wg.Add(1)
go dosomething(c, wg)
}
wg.Wait()
fmt.Println(c.sum)
fmt.Println(time.Since(t))
}
But I found that use a mutex pointer works too:
type calculation struct{
sum int
mutex *sync.Mutex
}
func dosomething(c *calculation , wg *sync.WaitGroup) {
c.mutex.Lock()
c.sum++
c.mutex.Unlock()
wg.Done()
}
func main() {
t := time.Now()
c := &calculation{0, new(sync.Mutex)}
wg := new(sync.WaitGroup)
for i:=0; i<10000000; i++{
wg.Add(1)
go dosomething(c, wg)
}
wg.Wait()
fmt.Println(c.sum)
fmt.Println(time.Since(t))
}
I made some tests on these 2 versions and found that there elapsed times are close.
So which one should I use? And Why should I use a mutex or mutex pointer? Are they have performance differences?
Upvotes: 0
Views: 2888
Reputation: 489333
A Go sync.Mutex
cannot be copied, so you would use a pointer to a (shared, non-copied) sync.Mutex
when you have a data structure that can be copied sensibly but that has some portion of itself that is shared and cannot be copied sensibly, and you plan to pass it around by value and/or return it, so that it gets copied.
For instance:
type Thingy struct {
notShared int
mtx *Sync.mutex
shared *int
}
func (t Thingy) Thingy {
t.notShared += 3
t.mtx.Lock()
*t.shared *= 2
t.mtx.Unlock()
return t
}
(It would probably be more typical to have multiple non-shared fields, and then one pointer to a struct
that contains both the mutex itself and the shared fields. The above is mainly for illustration)
Given that your calculation
structure is itself always passed around as a pointer, though, there's no reason to add a level of indirection to your example.
Edit: you added a question about performance differences. Adding an extra (otherwise-unnecessary) indirection often costs a bit in performance, but in general, you should just write the most readable code you can first, and then measure it for performance issues. Adding an extra unnecessary indirection tends to make the code slightly less readable, in my view, so here, performance and readability go together.
Upvotes: 6