面试题答案
一键面试在Go语言中,可以使用sync.Mutex
(互斥锁)来避免多个goroutine同时访问和修改共享资源时的资源竞争问题。以下是使用sync.Mutex
保护全局map
的代码示例:
package main
import (
"fmt"
"sync"
)
var (
globalMap = make(map[string]int)
mu sync.Mutex
)
func updateMap(key string, value int, wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock()
globalMap[key] = value
mu.Unlock()
}
func main() {
var wg sync.WaitGroup
keys := []string{"key1", "key2", "key3"}
values := []int{1, 2, 3}
for i := range keys {
wg.Add(1)
go updateMap(keys[i], values[i], &wg)
}
wg.Wait()
mu.Lock()
fmt.Println("Final globalMap:", globalMap)
mu.Unlock()
}
原理解释:
sync.Mutex
声明:代码中声明了一个sync.Mutex
类型的变量mu
。互斥锁的作用是保证在同一时刻只有一个goroutine能够访问被保护的资源。mu.Lock()
:在updateMap
函数中,通过mu.Lock()
来锁定互斥锁。这会阻止其他goroutine同时进入临界区(即修改globalMap
的代码段)。如果此时有其他goroutine尝试获取锁,它将被阻塞,直到当前持有锁的goroutine释放锁。- 修改共享资源:在获取锁之后,对
globalMap
进行修改操作,即globalMap[key] = value
。 mu.Unlock()
:修改完成后,通过mu.Unlock()
释放锁,允许其他goroutine获取锁并进入临界区进行操作。sync.WaitGroup
:在main
函数中,使用sync.WaitGroup
来等待所有的goroutine完成操作。wg.Add(1)
增加等待组的计数,defer wg.Done()
在goroutine结束时减少计数,wg.Wait()
阻塞主线程直到所有计数变为0,确保所有对globalMap
的修改都已完成。最后,在打印globalMap
之前再次获取锁,以保证读取操作的一致性。
这样,通过sync.Mutex
和sync.WaitGroup
,可以有效地避免多个goroutine同时访问和修改共享map
时的资源竞争问题。