在 Go语言 中,并发是其核心特性之一。通过 goroutine,我们可以轻松地启动成千上万个轻量级线程来执行任务。然而,当多个 goroutine 同时访问共享资源(如变量、切片、结构体等)时,就可能引发数据竞争(data race),导致程序行为不可预测甚至崩溃。
为了解决这个问题,Go 标准库提供了 sync.Mutex —— 一种互斥锁(Mutex),用于保证同一时间只有一个 goroutine 能访问临界区代码,从而实现线程安全。

sync.Mutex 是 Go 语言中用于保护共享资源不被多个 goroutine 同时修改的同步原语。它提供两个方法:
Lock():获取锁。如果锁已被其他 goroutine 持有,则当前 goroutine 会阻塞,直到锁被释放。Unlock():释放锁,允许其他等待的 goroutine 获取该锁。我们先看一个没有使用互斥锁的反面例子:
package mainimport ( "fmt" "sync")var counter intfunc main() { var wg sync.WaitGroup for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() counter++ // 多个 goroutine 同时修改 counter,存在数据竞争! }() } wg.Wait() fmt.Println("Final counter:", counter) // 结果通常小于 1000}运行这段代码,你会发现输出结果往往不是 1000,而是某个小于 1000 的数字。这是因为多个 goroutine 同时读取和写入 counter,导致某些自增操作被覆盖——这就是典型的数据竞争问题。
现在,我们引入 sync.Mutex 来保护对 counter 的访问:
package mainimport ( "fmt" "sync")var ( counter int mu sync.Mutex // 定义一个互斥锁)func main() { var wg sync.WaitGroup for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() mu.Lock() // 获取锁 counter++ // 安全地修改共享变量 mu.Unlock() // 释放锁 }() } wg.Wait() fmt.Println("Final counter:", counter) // 输出一定是 1000}这次,无论运行多少次,结果都是 1000!因为 mu.Lock() 和 mu.Unlock() 之间的代码构成了一个临界区,确保同一时刻只有一个 goroutine 能执行 counter++。
Unlock()。推荐使用 defer mu.Unlock(),避免因 panic 或提前 return 导致死锁。sync.Mutex 是不可复制的类型。将其作为结构体字段时,应使用指针或确保结构体不被复制。Lock()(除非使用 sync.RWMutex 或可重入锁,但 Go 默认 Mutex 不可重入)。在 Go语言 并发编程中,sync.Mutex 是实现线程安全最基础也最重要的工具之一。通过合理使用互斥锁,我们可以有效防止数据竞争,确保程序在高并发环境下的正确性。
记住:**共享内存 + 并发 = 需要同步机制**。而 sync.Mutex 正是你在 Go 中守护共享资源的第一道防线。
希望这篇教程能帮助你理解 sync.Mutex 互斥锁 的基本用法。动手试试吧!
本文由主机测评网于2025-12-21发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/20251210976.html