面试题答案
一键面试闭包在Go并发编程中的复杂性
- 资源竞争问题:闭包可能引用外部变量,在并发环境下多个协程同时访问和修改这些变量,就会导致资源竞争。
- 数据一致性问题:由于资源竞争,可能使得数据处于不一致的状态,例如某个变量的更新没有按照预期顺序完成。
代码示例及处理方法
package main
import (
"fmt"
"sync"
)
func main() {
var count int
var wg sync.WaitGroup
var mu sync.Mutex
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// 使用互斥锁来处理资源竞争
mu.Lock()
count++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println("Final count:", count)
}
在上述代码中,count
是被闭包引用的外部变量。通过使用 sync.Mutex
来加锁和解锁,确保每次只有一个协程能够修改 count
,从而解决资源竞争和保证数据一致性。如果不使用 mu.Lock()
和 mu.Unlock()
,多个协程同时对 count
进行 ++
操作,就会出现资源竞争,导致 count
的最终值可能小于预期的 10。
另外,还可以使用 sync/atomic
包来对一些基本类型(如 int
)进行原子操作,这也是处理并发数据一致性问题的一种有效方式,例如:
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var count int64
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
atomic.AddInt64(&count, 1)
}()
}
wg.Wait()
fmt.Println("Final count:", atomic.LoadInt64(&count))
}
这里使用 atomic.AddInt64
和 atomic.LoadInt64
对 int64
类型的 count
进行原子操作,避免了资源竞争,保证了数据一致性。