Z
ZHANK
并发编程

sync 同步原语

sync.Mutex/RWMutex、sync.WaitGroup、sync.Once、原子操作

sync 同步原语

channel 是 Go 并发的首选,但有时用传统同步原语更直接——sync.Mutexsync.WaitGroupsync.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)