16-第16章-并发控制与锁优化
·
第16章:并发控制与锁优化
16.1 并发基础
16.1.1 Goroutine 管理
// 使用 sync.WaitGroup 等待多个 goroutine
func ProcessTasks(tasks []Task) {
var wg sync.WaitGroup
for _, task := range tasks {
wg.Add(1)
go func(t Task) {
defer wg.Done()
t.Execute()
}(task)
}
wg.Wait()
}
// 使用 context 控制 goroutine 生命周期
func ProcessWithTimeout(ctx context.Context, duration time.Duration) error {
ctx, cancel := context.WithTimeout(ctx, duration)
defer cancel()
done := make(chan error, 1)
go func() {
done <- doWork()
}()
select {
case <-ctx.Done():
return ctx.Err()
case err := <-done:
return err
}
}
16.2 锁的使用
16.2.1 sync.Mutex
// 互斥锁基本使用
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
}
16.2.2 sync.RWMutex
// 读写锁:读多写少场景
type Cache struct {
mu sync.RWMutex
data map[string]interface{}
}
func (c *Cache) Get(key string) (interface{}, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
val, ok := c.data[key]
return val, ok
}
func (c *Cache) Set(key string, value interface{}) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = value
}
16.3 原子操作
16.3.1 sync/atomic 包
import "sync/atomic"
type AtomicCounter struct {
value int64
}
func (c *AtomicCounter) Inc() {
atomic.AddInt64(&c.value, 1)
}
func (c *AtomicCounter) Value() int64 {
return atomic.LoadInt64(&c.value)
}
func (c *AtomicCounter) CompareAndSwap(old, new int64) bool {
return atomic.CompareAndSwapInt64(&c.value, old, new)
}
16.3.2 原子操作 vs 锁
| 特性 | 原子操作 | 互斥锁 |
|---|---|---|
| 适用场景 | 简单操作 | 复杂操作 |
| 性能 | 高 | 较低 |
| 复杂度 | 低 | 中 |
| 可组合性 | 差 | 好 |
16.4 无锁数据结构
16.4.1 Channel 作为同步机制
// 使用 channel 实现工作池
type WorkerPool struct {
tasks chan Task
wg sync.WaitGroup
}
func NewWorkerPool(workerCount int) *WorkerPool {
pool := &WorkerPool{
tasks: make(chan Task, 100),
}
for i := 0; i < workerCount; i++ {
pool.wg.Add(1)
go pool.worker()
}
return pool
}
func (p *WorkerPool) worker() {
defer p.wg.Done()
for task := range p.tasks {
task.Execute()
}
}
func (p *WorkerPool) Submit(task Task) {
p.tasks <- task
}
func (p *WorkerPool) Close() {
close(p.tasks)
p.wg.Wait()
}
16.5 锁优化技巧
16.5.1 减少锁持有时间
// 不好的做法:锁持有时间长
func (c *Counter) ProcessAndIncrement(data []byte) {
c.mu.Lock()
defer c.mu.Unlock()
// 耗时操作在锁内
processData(data)
c.value++
}
// 好的做法:减少锁持有时间
func (c *Counter) ProcessAndIncrement(data []byte) {
// 耗时操作在锁外
processData(data)
c.mu.Lock()
c.value++
c.mu.Unlock()
}
16.5.2 锁分段
// 分段锁:减少锁竞争
type ShardedMap struct {
shards []*shard
count int
}
type shard struct {
mu sync.RWMutex
data map[string]interface{}
}
func NewShardedMap(shardCount int) *ShardedMap {
shards := make([]*shard, shardCount)
for i := range shards {
shards[i] = &shard{
data: make(map[string]interface{}),
}
}
return &ShardedMap{
shards: shards,
count: shardCount,
}
}
func (m *ShardedMap) getShard(key string) *shard {
h := fnv.New32a()
h.Write([]byte(key))
return m.shards[h.Sum32()%uint32(m.count)]
}
func (m *ShardedMap) Get(key string) (interface{}, bool) {
shard := m.getShard(key)
shard.mu.RLock()
defer shard.mu.RUnlock()
val, ok := shard.data[key]
return val, ok
}
func (m *ShardedMap) Set(key string, value interface{}) {
shard := m.getShard(key)
shard.mu.Lock()
defer shard.mu.Unlock()
shard.data[key] = value
}
16.6 实战练习
练习 16.1:无锁队列
实现一个无锁的队列数据结构。
练习 16.2:锁竞争分析
使用 go tool trace 分析锁竞争情况。
练习 16.3:性能对比
对比原子操作、互斥锁、读写锁的性能差异。
16.7 本章小结
本章深入讲解了并发控制和锁优化:
- Goroutine 管理和同步
- 互斥锁和读写锁的使用
- 原子操作
- 无锁数据结构
- 锁优化技巧
合理的并发控制是高性能系统的关键。
本书版本:1.0.0
最后更新:2026-03-08
sfsEdgeStore - 让边缘数据存储更简单!🚀
技术栈 - Go语言、sfsDb与EdgeX Foundry。纯golang工业物联网边缘计算技术栈
项目地址:GitHub
GitCode 镜像:GitCode
更多推荐
所有评论(0)