sync 同步原语
sync.Mutex/RWMutex、sync.WaitGroup、sync.Once、原子操作
sync 同步原语
channel 是 Go 并发的首选,但有时用传统同步原语更直接——sync.Mutex、sync.WaitGroup、sync.Once。
学完本章你将: 掌握 Mutex/RWMutex、WaitGroup、Once、原子操作。
sync.Mutex —— 互斥锁
go
package main
import (
"fmt"
"sync"
)
type Counter struct {
mu sync.Mutex
value int
}
func (c *Counter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.value++
}
func (c *Counter) Value() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.value
}
func main() {
var wg sync.WaitGroup
c := &Counter{}
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
c.Inc()
}()
}
wg.Wait()
fmt.Println(c.Value()) // 1000
}
sync.RWMutex —— 读写锁
go
var mu sync.RWMutex
// 读锁(允许多个同时读)
mu.RLock()
val := sharedData
mu.RUnlock()
// 写锁(独占)
mu.Lock()
sharedData = newValue
mu.Unlock()
sync.WaitGroup / sync.Once
go
// WaitGroup —— 等待一组 goroutine
var wg sync.WaitGroup
wg.Add(3)
go func() { defer wg.Done(); work1() }()
go func() { defer wg.Done(); work2() }()
go func() { defer wg.Done(); work3() }()
wg.Wait()
// Once —— 保证只执行一次
var once sync.Once
once.Do(func() { fmt.Println("只输出一次") })
atomic 原子操作
go
var count int64
// 原子递增(比 Mutex 轻量——无锁)
atomic.AddInt64(&count, 1)
val := atomic.LoadInt64(&count)