互斥锁(Mutex,Mutual Exclusion)是一种用于同步和保护共享资源的机制,它确保在同一时刻只有一个线程能够访问共享资源,从而避免多个线程同时修改共享数据时导致的竞争条件和数据不一致问题。
1.互斥锁的基本用法
-
声明互斥锁:
互斥锁通常使用
sync.Mutex类型声明,它有两个方法:-
Lock():锁定互斥锁,阻塞当前 goroutine,直到锁可用。 -
Unlock():解锁互斥锁,允许其他被阻塞的 goroutine 获取锁。
-
-
使用互斥锁:
在并发环境中,如果多个 goroutine 需要对共享资源进行读写操作,应该使用互斥锁来确保每次只有一个 goroutine 可以访问该资源。
举个例子:
package main
import (
"fmt"
"sync"
)
var (
mu sync.Mutex // 声明一个互斥锁
count int
)
func increment(wg *sync.WaitGroup) {
defer wg.Done() // 在函数结束时通知 WaitGroup
mu.Lock() // 上锁
count++ // 共享资源操作
mu.Unlock() // 解锁
}
func main() {
var wg sync.WaitGroup
// 启动多个 goroutine 进行并发操作
for i := 0; i < 5; i++ {
wg.Add(1)
go increment(&wg)
}
wg.Wait() // 等待所有 goroutine 完成
fmt.Println("Final count:", count)
}
2.代码解释
-
increment函数的作用是将count的值递增 1。 -
wg.Done():这是一个用来通知sync.WaitGroup当前 goroutine 完成的操作。sync.WaitGroup会在主 goroutine 中等待直到所有的并发操作完成。 -
mu.Lock():在访问共享资源count之前,首先需要锁定互斥锁mu,以保证同一时刻只有一个 goroutine 能修改count。 -
count++:这是修改共享资源count的操作,它会被并发的 goroutine 调用,必须确保该操作在锁定的状态下进行,避免多个 goroutine 同时修改count。 -
mu.Unlock():在count++操作完成后解锁,这样其他被阻塞的 goroutine 就可以获取锁并进行相应的操作。
所以,这个main主函数里最终由于互斥锁的保护,可以确保每次只有一个 goroutine 修改count,完成输出5,避免了多个 goroutine 同时访问共享资源导致的数据不一致。
3.关键点总结
-
互斥锁:通过
mu.Lock()和mu.Unlock()来确保只有一个 goroutine 可以修改count,防止多个 goroutine 同时访问共享资源导致的数据不一致。 -
sync.WaitGroup:用来等待所有的 goroutine 执行完成。主 goroutine 在wg.Wait()调用后会被阻塞,直到所有并发的increment函数执行完毕。 -
并发安全:程序通过互斥锁保证了并发修改共享资源
count时的安全性。
540

被折叠的 条评论
为什么被折叠?



