同步原语(sync包)

Mutex互斥锁

Mutex是最基本的同步原语,用于保护共享资源,确保同一时间只有一个goroutine可以访问。

package main

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

type SafeCounter struct {
    mu    sync.Mutex
    count int
}

func (c *SafeCounter) Increment() {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.count++
}

func (c *SafeCounter) GetCount() int {
    c.mu.Lock()
    defer c.mu.Unlock()
    return c.count
}

func main() {
    counter := &SafeCounter{}
    
    // 启动多个goroutine同时增加计数
    for i := 0; i < 1000; i++ {
        go counter.Increment()
    }
    
    time.Sleep(time.Second)
    fmt.Println("Final count:", counter.GetCount())
}

RWMutex读写锁

RWMutex允许多个goroutine同时读取,但写入时需要独占访问。

package main

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

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

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

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

func main() {
    m := &SafeMap{data: make(map[string]string)}
    
    // 写入操作
    go func() {
        for i := 0; i < 10; i++ {
            m.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("value%d", i))
        }
    }()
    
    // 多个goroutine同时读取
    for i := 0; i < 5; i++ {
        go func() {
            for j := 0; j < 10; j++ {
                fmt.Println(m.Get(fmt.Sprintf("key%d", j)))
            }
        }()
    }
    
    time.Sleep(time.Second)
}

WaitGroup

WaitGroup用于等待一组goroutine完成。

package main

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

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()
    
    fmt.Printf("Worker %d starting\n", id)
    time.Sleep(time.Second)
    fmt.Printf("Worker %d done\n", id)
}

func main() {
    var wg sync.WaitGroup
    
    // 启动5个worker
    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker(i, &wg)
    }
    
    // 等待所有worker完成
    wg.Wait()
    fmt.Println("All workers completed")
}

Once

Once确保某个函数只执行一次,常用于初始化操作。

package main

import (
    "fmt"
    "sync"
)

type Singleton struct {
    value int
}

var (
    instance *Singleton
    once     sync.Once
)

func GetInstance() *Singleton {
    once.Do(func() {
        instance = &Singleton{value: 42}
        fmt.Println("Singleton initialized")
    })
    return instance
}

func main() {
    // 多次调用GetInstance,但初始化只执行一次
    for i := 0; i < 5; i++ {
        go func() {
            instance := GetInstance()
            fmt.Println("Got instance with value:", instance.value)
        }()
    }
}

Cond条件变量

Cond用于goroutine之间的条件等待和通知。

package main

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

func main() {
    var m sync.Mutex
    c := sync.NewCond(&m)
    queue := make([]int, 0)
    
    // 消费者
    go func() {
        for {
            m.Lock()
            for len(queue) == 0 {
                c.Wait()
            }
            item := queue[0]
            queue = queue[1:]
            fmt.Println("Consumed:", item)
            m.Unlock()
        }
    }()
    
    // 生产者
    for i := 0; i < 5; i++ {
        m.Lock()
        queue = append(queue, i)
        fmt.Println("Produced:", i)
        c.Signal()
        m.Unlock()
        time.Sleep(time.Millisecond * 100)
    }
}

Pool对象池

Pool用于存储和复用临时对象,减少内存分配和垃圾回收压力。

package main

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

type Buffer struct {
    data []byte
}

func main() {
    var pool sync.Pool
    
    // 定义创建新对象的方法
    pool.New = func() interface{} {
        return &Buffer{data: make([]byte, 1024)}
    }
    
    // 使用对象池
    for i := 0; i < 10; i++ {
        go func() {
            // 获取对象
            buf := pool.Get().(*Buffer)
            defer pool.Put(buf)
            
            // 使用对象
            time.Sleep(time.Millisecond * 100)
            fmt.Println("Using buffer of size:", len(buf.data))
        }()
    }
    
    time.Sleep(time.Second)
}

Map并发安全映射

sync.Map是并发安全的map实现,适用于读多写少的场景。

package main

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

func main() {
    var m sync.Map
    
    // 写入操作
    for i := 0; i < 10; i++ {
        go func(i int) {
            m.Store(i, i*i)
        }(i)
    }
    
    // 读取操作
    for i := 0; i < 10; i++ {
        go func(i int) {
            if value, ok := m.Load(i); ok {
                fmt.Printf("Key: %d, Value: %v\n", i, value)
            }
        }(i)
    }
    
    // 使用LoadOrStore
    value, loaded := m.LoadOrStore(5, 25)
    fmt.Printf("Value: %v, Loaded: %v\n", value, loaded)
    
    // 使用Range遍历
    m.Range(func(key, value interface{}) bool {
        fmt.Printf("Key: %v, Value: %v\n", key, value)
        return true
    })
    
    time.Sleep(time.Second)
}