Mutex用于解决多goroutine并发访问共享资源时的数据竞争问题,通过Lock和Unlock确保同一时间只有一个goroutine能访问临界区,示例中使用defer保证解锁,实现计数器安全递增。

在Go语言中,Mutex(互斥锁)用于保护共享资源,防止多个goroutine同时访问造成数据竞争。当多个goroutine并发读写同一变量时,使用 sync.Mutex 能确保在同一时刻只有一个goroutine可以进入临界区。
为什么需要Mutex?
Go的并发模型基于goroutine和channel,但当多个goroutine操作同一个变量时,比如对一个map或计数器进行写操作,不加保护会导致竞态条件(race condition)。例如:
两个goroutine同时对一个全局变量i执行i++,可能最终结果只加了1,而不是2。这时就需要使用 sync.Mutex 来保证操作的原子性。
如何正确使用Mutex
使用 sync.Mutex 的基本方式是:在访问共享资源前调用 Lock(),操作完成后立即调用 Unlock()。通常配合 defer 使用,确保解锁不会被遗漏。
立即学习“go语言免费学习笔记(深入)”;
免费 盛世企业网站管理系统(SnSee)系统完全免费使用,无任何功能模块使用限制,在使用过程中如遇到相关问题可以去官方论坛参与讨论。开源 系统Web代码完全开源,在您使用过程中可以根据自已实际情况加以调整或修改,完全可以满足您的需求。强大且灵活 独创的多语言功能,可以直接在后台自由设定语言版本,其语言版本不限数量,可根据自已需要进行任意设置;系统各模块可在后台自由设置及开启;强大且适用的后台管理支
示例:安全地增加计数器
package main
import (
"fmt"
"sync"
)
var (
counter = 0
mutex sync.Mutex
)
func increment(wg *sync.WaitGroup) {
defer wg.Done()
mutex.Lock()
defer mutex.Unlock()
counter++
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go increment(&wg)
}
wg.Wait()
fmt.Println("Final counter:", counter) // 输出: 1000
}
在这个例子中,每次对 counter 的修改都由 mutex 保护,避免了数据竞争。
常见使用场景和注意事项
- 保护结构体字段:如果一个结构体包含多个goroutine共享的字段,可以在结构体中嵌入Mutex。
-
读写频繁时考虑使用RWMutex:如果读操作远多于写操作,使用
sync.RWMutex可提升性能,允许多个读操作并发执行。 -
避免死锁:确保每次Lock都有对应的Unlock,推荐用
defer mutex.Unlock()。 - 不要复制包含Mutex的结构体:复制会导致锁失效或引发panic。
- 作用范围要小:临界区代码应尽量短,避免在Lock期间做耗时操作(如网络请求)。
总结
在多goroutine环境中,只要存在对共享变量的写操作,就必须使用Mutex进行同步。正确使用 sync.Mutex 能有效防止数据竞争,保障程序正确性。关键是:先Lock,操作完Unlock,并优先使用defer来释放锁。
基本上就这些,不复杂但容易忽略细节。









