面试题答案
一键面试常见并发场景
- 共享资源访问:当多个 goroutine 需要访问和修改共享的变量、数据结构(如 map、slice 等)时,Mutex 锁可以防止竞态条件,确保同一时间只有一个 goroutine 能访问和修改共享资源。例如,多个 goroutine 同时向一个共享的计数器加 1 操作。
- 保护临界区:临界区是指程序中访问共享资源的代码段。Mutex 用于保护临界区,使得每次只有一个 goroutine 能够进入临界区执行代码。比如数据库连接池的获取和释放连接操作,连接池是共享资源,获取和释放操作就是临界区,需要用 Mutex 锁保护。
示例代码
package main
import (
"fmt"
"sync"
)
var (
counter int
mu sync.Mutex
)
func increment(wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock()
counter++
mu.Unlock()
}
func main() {
var wg sync.WaitGroup
numGoroutines := 1000
for i := 0; i < numGoroutines; i++ {
wg.Add(1)
go increment(&wg)
}
wg.Wait()
fmt.Println("Final counter value:", counter)
}
在这段代码中,counter
是一个共享变量,多个 goroutine 通过 increment
函数对其进行增加操作。mu
是一个 sync.Mutex
实例,用于保护 counter
变量。在 increment
函数中,先调用 mu.Lock()
锁定 Mutex,这样其他 goroutine 就无法同时进入临界区修改 counter
,操作完成后调用 mu.Unlock()
解锁,允许其他 goroutine 访问。在 main
函数中,启动 1000 个 goroutine 并发执行 increment
函数,最后输出 counter
的最终值。如果不使用 Mutex 锁,由于竞态条件,counter
的最终值可能小于 1000。