1 锁机制

1.1 互斥锁:Mutex

01.Mutex基本概念
    a.定义
        互斥锁用于保护共享资源,同一时刻只允许一个goroutine访问
    b.特点
        提供Lock和Unlock方法
        不可重入
        零值可用

02.基本使用
    a.Lock和Unlock
        ---
        package main

        import (
            "fmt"
            "sync"
        )

        var (
            counter int
            mu      sync.Mutex
        )

        func main() {
            for i := 0; i < 10; i++ {
                go increment()
            }
            time.Sleep(time.Second)
            fmt.Println("Counter:", counter)
        }

        func increment() {
            mu.Lock()
            counter++
            mu.Unlock()
        }
        ---

03.defer释放锁
    a.最佳实践
        ---
        func safeIncrement() {
            mu.Lock()
            defer mu.Unlock()
            counter++
        }
        ---

04.常见错误
    a.忘记释放锁
        导致死锁
    b.重复加锁
        同一goroutine重复Lock会死锁

1.2 读写锁:RWMutex

01.RWMutex基本概念
    a.定义
        读写锁允许多个读者或一个写者
    b.方法
        RLock/RUnlock:读锁
        Lock/Unlock:写锁

02.基本使用
    a.读写分离
        ---
        package main

        import (
            "fmt"
            "sync"
            "time"
        )

        var (
            data = make(map[string]int)
            rwmu sync.RWMutex
        )

        func read(key string) int {
            rwmu.RLock()
            defer rwmu.RUnlock()
            return data[key]
        }

        func write(key string, value int) {
            rwmu.Lock()
            defer rwmu.Unlock()
            data[key] = value
        }

        func main() {
            for i := 0; i < 5; i++ {
                go func(n int) {
                    write(fmt.Sprintf("key%d", n), n)
                }(i)
            }

            time.Sleep(time.Millisecond * 100)

            for i := 0; i < 10; i++ {
                go func(n int) {
                    fmt.Println(read(fmt.Sprintf("key%d", n%5)))
                }(i)
            }

            time.Sleep(time.Second)
        }
        ---

03.适用场景
    a.读多写少
        多个goroutine可以同时读取
    b.性能优势
        读操作不互斥,提高并发性

1.3 原子操作:atomic包

01.atomic包概述
    a.提供的类型
        atomic.Int32/Int64
        atomic.Uint32/Uint64
        atomic.Bool
        atomic.Pointer
    b.特点
        无锁操作
        性能高于Mutex

02.基本操作
    a.Add和Load/Store
        ---
        package main

        import (
            "fmt"
            "sync"
            "sync/atomic"
        )

        func main() {
            var counter int64

            var wg sync.WaitGroup
            for i := 0; i < 100; i++ {
                wg.Add(1)
                go func() {
                    defer wg.Done()
                    atomic.AddInt64(&counter, 1)
                }()
            }

            wg.Wait()
            fmt.Println("Counter:", atomic.LoadInt64(&counter))
        }
        ---
    b.CompareAndSwap
        ---
        var value int64 = 10

        // CAS操作
        swapped := atomic.CompareAndSwapInt64(&value, 10, 20)
        fmt.Println("Swapped:", swapped, "Value:", value)
        ---

03.atomic.Value
    a.存储任意类型
        ---
        var config atomic.Value

        // 存储配置
        config.Store(map[string]string{"key": "value"})

        // 读取配置
        cfg := config.Load().(map[string]string)
        fmt.Println(cfg["key"])
        ---

1.4 Once:单次执行

01.Once基本概念
    a.定义
        确保某个操作只执行一次
    b.应用场景
        单例模式
        初始化操作

02.基本使用
    a.Do方法
        ---
        package main

        import (
            "fmt"
            "sync"
        )

        var once sync.Once

        func initialize() {
            fmt.Println("初始化...")
        }

        func main() {
            for i := 0; i < 10; i++ {
                go func() {
                    once.Do(initialize)
                }()
            }
            time.Sleep(time.Second)
        }
        ---

03.单例模式
    a.线程安全的单例
        ---
        type Singleton struct {
            data string
        }

        var (
            instance *Singleton
            once     sync.Once
        )

        func GetInstance() *Singleton {
            once.Do(func() {
                instance = &Singleton{data: "singleton"}
            })
            return instance
        }
        ---

1.5 WaitGroup:等待组

01.WaitGroup基本概念
    a.定义
        等待一组goroutine完成
    b.方法
        Add:增加计数
        Done:减少计数
        Wait:等待计数归零

02.基本使用
    a.等待多个goroutine
        ---
        package main

        import (
            "fmt"
            "sync"
            "time"
        )

        func main() {
            var wg sync.WaitGroup

            for i := 0; i < 5; i++ {
                wg.Add(1)
                go func(n int) {
                    defer wg.Done()
                    fmt.Printf("Goroutine %d\n", n)
                    time.Sleep(time.Millisecond * 100)
                }(i)
            }

            wg.Wait()
            fmt.Println("所有goroutine完成")
        }
        ---

03.常见错误
    a.Add和Done不匹配
        导致Wait永久阻塞或panic
    b.在goroutine内Add
        可能导致竞态条件
        ---
        // 错误
        go func() {
            wg.Add(1)
            defer wg.Done()
        }()

        // 正确
        wg.Add(1)
        go func() {
            defer wg.Done()
        }()
        ---

2 同步原语

2.1 Channel通道

01.Channel基本概念
    a.定义
        goroutine之间通信的管道
    b.类型
        无缓冲channel:同步通信
        有缓冲channel:异步通信

02.基本使用
    a.创建和发送接收
        ---
        package main

        import "fmt"

        func main() {
            ch := make(chan int)

            go func() {
                ch <- 42
            }()

            value := <-ch
            fmt.Println(value)
        }
        ---
    b.有缓冲channel
        ---
        ch := make(chan int, 3)
        ch <- 1
        ch <- 2
        ch <- 3

        fmt.Println(<-ch)
        fmt.Println(<-ch)
        fmt.Println(<-ch)
        ---

03.关闭channel
    a.close函数
        ---
        ch := make(chan int, 2)
        ch <- 1
        ch <- 2
        close(ch)

        for v := range ch {
            fmt.Println(v)
        }
        ---

2.2 Select多路复用

01.Select基本概念
    a.定义
        同时等待多个channel操作
    b.特点
        随机选择就绪的case
        default提供非阻塞操作

02.基本使用
    a.多路选择
        ---
        package main

        import (
            "fmt"
            "time"
        )

        func main() {
            ch1 := make(chan string)
            ch2 := make(chan string)

            go func() {
                time.Sleep(time.Second)
                ch1 <- "from ch1"
            }()

            go func() {
                time.Sleep(time.Second * 2)
                ch2 <- "from ch2"
            }()

            for i := 0; i < 2; i++ {
                select {
                case msg1 := <-ch1:
                    fmt.Println(msg1)
                case msg2 := <-ch2:
                    fmt.Println(msg2)
                }
            }
        }
        ---

03.超时控制
    a.time.After
        ---
        select {
        case msg := <-ch:
            fmt.Println(msg)
        case <-time.After(time.Second):
            fmt.Println("超时")
        }
        ---

2.3 Context上下文

01.Context基本概念
    a.定义
        携带截止时间、取消信号、请求值
    b.类型
        context.Background()
        context.TODO()
        context.WithCancel()
        context.WithTimeout()
        context.WithDeadline()
        context.WithValue()

02.取消控制
    a.WithCancel
        ---
        package main

        import (
            "context"
            "fmt"
            "time"
        )

        func main() {
            ctx, cancel := context.WithCancel(context.Background())

            go func() {
                for {
                    select {
                    case <-ctx.Done():
                        fmt.Println("goroutine退出")
                        return
                    default:
                        fmt.Println("工作中...")
                        time.Sleep(time.Millisecond * 500)
                    }
                }
            }()

            time.Sleep(time.Second * 2)
            cancel()
            time.Sleep(time.Second)
        }
        ---

03.超时控制
    a.WithTimeout
        ---
        ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
        defer cancel()

        select {
        case <-time.After(time.Second * 3):
            fmt.Println("操作完成")
        case <-ctx.Done():
            fmt.Println("超时:", ctx.Err())
        }
        ---

2.4 Cond条件变量

01.Cond基本概念
    a.定义
        条件变量用于goroutine间的通知
    b.方法
        Wait:等待通知
        Signal:通知一个等待者
        Broadcast:通知所有等待者

02.基本使用
    a.生产者消费者
        ---
        package main

        import (
            "fmt"
            "sync"
            "time"
        )

        func main() {
            var mu sync.Mutex
            cond := sync.NewCond(&mu)
            queue := make([]int, 0)

            // 消费者
            go func() {
                mu.Lock()
                for len(queue) == 0 {
                    cond.Wait()
                }
                item := queue[0]
                queue = queue[1:]
                mu.Unlock()
                fmt.Println("消费:", item)
            }()

            // 生产者
            time.Sleep(time.Second)
            mu.Lock()
            queue = append(queue, 1)
            cond.Signal()
            mu.Unlock()

            time.Sleep(time.Second)
        }
        ---

3 并发模式

3.1 生产者消费者模式

01.基本实现
    a.使用channel
        ---
        package main

        import (
            "fmt"
            "time"
        )

        func producer(ch chan<- int) {
            for i := 0; i < 5; i++ {
                ch <- i
                fmt.Println("生产:", i)
                time.Sleep(time.Millisecond * 100)
            }
            close(ch)
        }

        func consumer(ch <-chan int) {
            for v := range ch {
                fmt.Println("消费:", v)
                time.Sleep(time.Millisecond * 200)
            }
        }

        func main() {
            ch := make(chan int, 2)
            go producer(ch)
            consumer(ch)
        }
        ---

3.2 工作池模式

01.工作池实现
    a.固定数量worker
        ---
        package main

        import (
            "fmt"
            "sync"
        )

        func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
            defer wg.Done()
            for job := range jobs {
                fmt.Printf("Worker %d 处理任务 %d\n", id, job)
                results <- job * 2
            }
        }

        func main() {
            jobs := make(chan int, 10)
            results := make(chan int, 10)

            var wg sync.WaitGroup
            for i := 1; i <= 3; i++ {
                wg.Add(1)
                go worker(i, jobs, results, &wg)
            }

            for i := 1; i <= 5; i++ {
                jobs <- i
            }
            close(jobs)

            wg.Wait()
            close(results)

            for result := range results {
                fmt.Println("结果:", result)
            }
        }
        ---

3.3 扇入扇出模式

01.扇出模式
    a.一个输入多个输出
        ---
        func fanOut(input <-chan int, n int) []<-chan int {
            outputs := make([]<-chan int, n)
            for i := 0; i < n; i++ {
                outputs[i] = process(input)
            }
            return outputs
        }

        func process(input <-chan int) <-chan int {
            out := make(chan int)
            go func() {
                defer close(out)
                for v := range input {
                    out <- v * 2
                }
            }()
            return out
        }
        ---

02.扇入模式
    a.多个输入一个输出
        ---
        func fanIn(channels ...<-chan int) <-chan int {
            out := make(chan int)
            var wg sync.WaitGroup

            for _, ch := range channels {
                wg.Add(1)
                go func(c <-chan int) {
                    defer wg.Done()
                    for v := range c {
                        out <- v
                    }
                }(ch)
            }

            go func() {
                wg.Wait()
                close(out)
            }()

            return out
        }
        ---

3.4 管道模式

01.管道实现
    a.多阶段处理
        ---
        package main

        import "fmt"

        func gen(nums ...int) <-chan int {
            out := make(chan int)
            go func() {
                for _, n := range nums {
                    out <- n
                }
                close(out)
            }()
            return out
        }

        func square(in <-chan int) <-chan int {
            out := make(chan int)
            go func() {
                for n := range in {
                    out <- n * n
                }
                close(out)
            }()
            return out
        }

        func main() {
            c := gen(2, 3, 4)
            out := square(c)

            for v := range out {
                fmt.Println(v)
            }
        }
        ---

4 锁的最佳实践

4.1 死锁预防

01.死锁原因
    a.循环等待
        多个goroutine互相等待对方释放锁
    b.预防方法
        按固定顺序获取锁
        使用超时机制
        避免嵌套锁

02.示例
    a.死锁场景
        ---
        var mu1, mu2 sync.Mutex

        // goroutine 1
        mu1.Lock()
        mu2.Lock()

        // goroutine 2
        mu2.Lock()
        mu1.Lock()
        ---
    b.解决方案
        ---
        // 统一顺序
        mu1.Lock()
        mu2.Lock()
        defer mu2.Unlock()
        defer mu1.Unlock()
        ---

4.2 锁粒度控制

01.细粒度锁
    a.减少锁竞争
        ---
        type SafeMap struct {
            mu   sync.RWMutex
            data map[string]int
        }

        func (m *SafeMap) Get(key string) int {
            m.mu.RLock()
            defer m.mu.RUnlock()
            return m.data[key]
        }

        func (m *SafeMap) Set(key string, value int) {
            m.mu.Lock()
            defer m.mu.Unlock()
            m.data[key] = value
        }
        ---

02.分段锁
    a.提高并发性
        ---
        type ShardedMap struct {
            shards []*Shard
        }

        type Shard struct {
            mu   sync.RWMutex
            data map[string]int
        }

        func (m *ShardedMap) getShard(key string) *Shard {
            hash := hash(key)
            return m.shards[hash%len(m.shards)]
        }
        ---

4.3 性能优化

01.选择合适的锁
    a.Mutex vs RWMutex
        读多写少用RWMutex
        简单场景用Mutex
    b.Mutex vs atomic
        简单计数用atomic
        复杂操作用Mutex

02.减少锁持有时间
    a.最佳实践
        ---
        // 不好
        mu.Lock()
        result := expensiveOperation()
        data = result
        mu.Unlock()

        // 好
        result := expensiveOperation()
        mu.Lock()
        data = result
        mu.Unlock()
        ---

4.4 常见陷阱

01.锁拷贝
    a.问题
        Mutex不能拷贝
        ---
        // 错误
        type Counter struct {
            mu    sync.Mutex
            count int
        }

        func (c Counter) Inc() { // 值接收者会拷贝
            c.mu.Lock()
            c.count++
            c.mu.Unlock()
        }

        // 正确
        func (c *Counter) Inc() { // 指针接收者
            c.mu.Lock()
            c.count++
            c.mu.Unlock()
        }
        ---

02.defer释放锁
    a.最佳实践
        ---
        func safeOperation() {
            mu.Lock()
            defer mu.Unlock()
            // 操作...
        }
        ---

03.忘记释放锁
    a.使用defer
        确保锁一定被释放