同步原语(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)
}