ZBLOG

sync.Mutex

sync.Mutex 是 Go 语言标准库 sync 包中提供的互斥锁(Mutual Exclusion Lock)类型,用于在并发编程中保护共享资源的访问,避免多个 goroutine 同时修改数据导致的竞态条件(Race Condition)。以下是关于 sync.Mutex 的详细说明和使用示例:


1. 核心特性

  • 互斥锁:同一时刻只有一个 goroutine 能持有锁,其他 goroutine 必须等待锁释放。
  • 零值可用:无需初始化即可直接使用(如 var mu sync.Mutex)。
  • 不可重入:同一个 goroutine 重复加锁会导致死锁(与某些语言的可重入锁不同)。

2. 基本方法

type Mutex struct {
    // 内部状态字段(对用户透明)
}

func (m *Mutex) Lock()     // 加锁(阻塞直到获取锁)
func (m *Mutex) Unlock()   // 解锁(必须在Lock后调用)

3. 使用示例

示例1:保护共享变量

package main

import (
	"fmt"
	"sync"
)

var (
	counter int
	mu      sync.Mutex
	wg      sync.WaitGroup
)

func increment() {
	defer wg.Done()
	mu.Lock()         // 加锁
	counter++         // 操作共享变量
	mu.Unlock()       // 解锁
}

func main() {
	for i :=0; i <1000; i++ {
		wg.Add(1)
		go increment()
	}
	wg.Wait()
	fmt.Println("Counter:", counter) // 输出: Counter:1000 (无竞态)
}

示例2:结合 defer 确保解锁

func safeWrite(data map[string]int, key string, value int) {
	var mu sync.Mutex
	mu.Lock()
	defer mu.Unlock() // defer保证即使发生panic也能解锁
	
	data[key] = value
}

4. 注意事项

  1. 避免死锁

    • Unlock()必须和Lock()成对出现。
    • 不可在未Lock时调用Unlock(会触发panic)。
    var mu sync.Mutex
    mu.Unlock() // panic: unlock of unlocked mutex
    
  2. 性能考虑

    • Mutex有一定开销,高并发场景下可考虑 sync.RWMutex(读写分离锁)。
    • 减少临界区代码量(锁定时间越短越好)。
  3. 非递归锁

    func deadlockExample() {
       var mu sync.Mutex
       mu.Lock()
       mu.Lock() // fatal error: all goroutines are asleep - deadlock!
    }
    

5. vs Channel

  • 适用场景对比: | 场景 | 推荐方式 | |————————|——————| |保护简单共享变量 | sync.Mutex | |协调多阶段复杂任务 | channel |

6. RWMutex扩展

如果需要更高效率的读多写少场景,可以使用 sync.RWMutex

var rwMu sync.RWMutoex

//读操作(允许多个goroutine同时读)
rwMu.RLock()
defer rwMu.RUnlock()

//写操作(独占)
rwMu.Lock()
defer rwMu.Unlock()

通过合理使用 sync.Mutex,可以确保 Go 并发程序的数据安全性。建议结合 go vet或竞态检测工具(-race)验证代码正确性。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=24043

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?