使用 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