闭包在Go语言并发编程场景下安全性相关问题
- 数据竞争问题:
- 问题阐述:当多个goroutine通过闭包访问和修改共享变量时,可能会出现数据竞争。由于Go语言的并发执行特性,多个goroutine可能同时访问和修改同一变量,导致结果不可预测。
- 示例:
package main
import (
"fmt"
"sync"
)
func main() {
var num int
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
num++
}()
}
wg.Wait()
fmt.Println("Final value of num:", num)
}
- 分析:在上述代码中,多个goroutine通过闭包访问和修改
num
变量。由于没有同步机制,不同goroutine对num
的操作可能会相互干扰,导致最终num
的值不一定是10。
- 闭包变量捕获延迟问题:
- 问题阐述:在循环中创建闭包时,如果闭包捕获了循环变量,可能会出现变量值并非如预期那样在闭包创建时被固定,而是在闭包执行时获取循环变量的当前值。在并发场景下,这种延迟捕获可能导致意外结果。
- 示例:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
var results []func()
for i := 0; i < 3; i++ {
wg.Add(1)
results = append(results, func() {
defer wg.Done()
fmt.Println(i)
})
}
for _, f := range results {
f()
}
wg.Wait()
}
- 分析:这里闭包捕获了循环变量
i
。预期输出是0、1、2,但实际输出可能是3、3、3。因为闭包捕获的是i
的引用,当闭包执行时,i
已经变成了循环结束后的最终值3。