使用 sync.Mutex 与 sync.WaitGroup
线程不安全的用法:
{
var wg sync.WaitGroup
count := 0
for i := 0; i < 10; i++ {
// wg add 1 goroutine
wg.Add(1)
// goroutine
go func() {
defer wg.Done()
for i := 0; i < 10000; i++ {
// unsafe increment
count++
}
}()
}
wg.Wait()
fmt.Println(count)
}
加锁,线程安全:
{
var myLock sync.Mutex
var wg sync.WaitGroup
count := 0
for i := 0; i < 10; i++ {
// wg add 1 goroutine
wg.Add(1)
// goroutine
go func() {
defer wg.Done()
for i := 0; i < 10000; i++ {
// safe increment
myLock.Lock()
count++
myLock.Unlock()
}
}()
}
wg.Wait()
fmt.Println(count)
}
其中一个运行输出:
53546
100000
自定义一个safe Counter
package counter
import (
"log"
"sync"
)
type Counter struct {
mu *sync.Mutex
Value int
}
func NewCounter(value int) *Counter {
return &Counter{
new(sync.Mutex), 0,
}
}
func (c *Counter) Increment() {
c.mu.Lock()
// defer func
defer func() {
c.mu.Unlock()
log.Printf("mu sync.Mutex Unlocked!")
}()
// safe increment Value
c.Value++
}
使用 safe Counter
{
var wg sync.WaitGroup
count := counter.NewCounter(0)
for i := 0; i < 10; i++ {
// wg add 1 goroutine
wg.Add(1)
// goroutine
go func() {
defer wg.Done()
for i := 0; i < 10000; i++ {
// safe increment
count.Increment()
}
}()
}
wg.Wait()
fmt.Println(count.Value)
}
正确输出:
100000