面试题答案
一键面试package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.Mutex
sharedVar := 0
increment := func() {
mu.Lock()
sharedVar++
mu.Unlock()
}
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
increment()
}()
}
wg.Wait()
fmt.Println("Final value:", sharedVar)
}
实现思路
- 定义共享变量和互斥锁:首先定义一个共享变量
sharedVar
,并创建一个sync.Mutex
类型的互斥锁mu
,用于保护对sharedVar
的访问。 - 创建闭包:
increment
闭包函数封装了对共享变量sharedVar
的修改操作。在闭包内部,通过调用mu.Lock()
锁定互斥锁,这样在同一时间只有一个 goroutine 能够进入临界区,对sharedVar
进行操作。操作完成后,调用mu.Unlock()
解锁互斥锁,允许其他 goroutine 访问。 - 启动多个 goroutine:在
main
函数中,使用for
循环启动 10 个 goroutine,每个 goroutine 都调用increment
闭包函数。通过sync.WaitGroup
等待所有 goroutine 完成操作。
保证数据安全的原因
这种方式能保证数据安全是因为互斥锁的机制。互斥锁只有两种状态:锁定和未锁定。当一个 goroutine 调用 mu.Lock()
时,如果互斥锁处于未锁定状态,它会将其锁定并进入临界区。如果互斥锁已经被锁定,调用 mu.Lock()
的 goroutine 会被阻塞,直到互斥锁被解锁。这样就确保了在任何时刻,只有一个 goroutine 能够访问和修改共享变量 sharedVar
,从而避免了数据竞争问题。