Mutex,互斥锁。
一个简单的互斥锁实现:
package main
import (
"fmt"
"sync"
)
func main() {
var count = 0
var wg sync.WaitGroup
wg.Add(10)
mu := sync.Mutex{}
for i := 0; i < 10; i++ {
go func() {
defer wg.Done()
for j := 0; j < 100000; j++ {
mu.Lock()
count++
mu.Unlock()
}
}()
}
wg.Wait()
fmt.Println(count)
}
下面是一个复杂的但是很经典的升级版实现。将 Mutex 藏在 结构体和 func 函数里。
package main
import (
"fmt"
"sync"
)
type Counter struct {
CounterType int
Name string
mu sync.Mutex
count uint64
}
// Inc 递增函数,内部使用互斥锁保护
func (c *Counter) Inc() {
c.mu.Lock()
c.count++
c.mu.Unlock()
}
// Count得到计数器的值,也许要锁保护
func (c *Counter) Count() uint64 {
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}
func main() {
var counter Counter
var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i++ {
go func() {
defer wg.Done()
for j := 0; j < 100000; j++ {
counter.Inc()
}
}()
}
wg.Wait()
fmt.Println(counter.Count())
}
如果读操作多余写操作
使用 sync.RWMutex
。允许多个 goroutine 同时读取计数器的值,但是只允许一个 goroutine 写入。
package main
import (
"fmt"
"sync"
)
type Counter struct {
CounterType int
Name string
mu sync.RWMutex
count uint64
}
func (c *Counter) Inc() {
c.mu.Lock()
c.count++
c.mu.Unlock()
}
func (c *Counter) Count() uint64 {
c.mu.RLock()
defer c.mu.RUnlock()
return c.count
}
func main() {
var counter Counter
var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i++ {
go func() {
defer wg.Done()
for i := 0; i < 100000; i++ {
counter.Inc()
}
}()
}
wg.Wait()
fmt.Println(counter.Count())
}