面试题答案
一键面试潜在问题
- 资源竞争:当多个goroutine通过defer操作共享资源时,可能会出现资源竞争问题。例如多个goroutine同时对同一个文件进行写入操作,若没有适当的同步机制,数据可能会出现错乱。
- 内存泄漏:如果在defer函数中持有对一些资源的引用,而这些资源没有被正确释放,可能会导致内存泄漏。比如在defer函数中忘记关闭文件句柄。
多个goroutine中使用defer操作共享资源的问题及解决
在多个goroutine中使用defer操作共享资源,最常见的问题就是资源竞争。例如,多个goroutine可能会同时尝试对共享的map进行写入操作,这会导致数据不一致。
解决办法是使用Go语言提供的同步机制,如sync.Mutex
(互斥锁)来保护共享资源。
代码示例
package main
import (
"fmt"
"sync"
)
var (
sharedMap = make(map[string]int)
mu sync.Mutex
)
func updateMap(key string, value int) {
mu.Lock()
defer mu.Unlock()
sharedMap[key] = value
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
key := fmt.Sprintf("key%d", id)
updateMap(key, id)
}(i)
}
wg.Wait()
fmt.Println(sharedMap)
}
代码分析
- 共享资源与锁的定义:定义了一个共享的
map
(sharedMap
)和一个互斥锁(mu
)。 - 更新共享资源的函数:
updateMap
函数使用mu.Lock()
锁定互斥锁,在函数结束时通过defer mu.Unlock()
解锁。这样就保证了在同一时间只有一个goroutine可以操作sharedMap
。 - 并发操作:在
main
函数中,启动10个goroutine并发调用updateMap
函数。每个goroutine完成后调用wg.Done()
通知等待组。 - 等待所有goroutine完成:
wg.Wait()
等待所有goroutine完成,然后打印sharedMap
,此时sharedMap
中的数据是正确更新且不会出现数据竞争导致的不一致问题。