解决的问题:
解决变量懒加载情况下并发请求数据竞争的问题。
懒加载的Demo:
var icons map[string]int
func loadIcons() {
icons = map[string] int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
}
}
// 并发不安全
func Icon(name string) int {
if icons == nil {
loadIcons() // 懒加载的行为 只有在将要使用的时候再进行初始化
}
return icons[name]
}
使用互斥锁的机制实现并发的懒加载:
import "sync"
var mu sync.RWMutex
var icons map[string]int
func loadIcons() {
icons = map[string] int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
}
}
// 并发安全的
func Icon(name string) int {
// 读锁 保证了读的并发安全性
mu.RLock()
if icons != nil {
icon := icons[name]
mu.RUnlock()
return icon
}
mu.RUnlock()
// 互斥锁, 保证了初始化变量的并发安全性。
mu.Lock()
if icons == nil {
loadIcons()
}
icon := icons[name]
mu.Unlock()
return icon
}
显然互斥锁的部分,再初次执行后,后面永远不可能执行到。显得代码非常的麻烦。
sync.Once 可以优化这种情况。
var loadIconsOnce sync.Once
var icons map[string] int
func Icon(name string) int {
loadIconsOnce.Do(loadIcons)
return icons[name]
}
sync.Once 一次性的初始化需要一个互斥量mutex和一个boolean变量来记录初始化是不是已经完成了。mutex同步会保证loadIcons对内存产生的效果能够对所有 sync.Once初始化goroutine可见。用这种方式来使用sync.Once的话,我们能够避免在变量被构建完成之前和其它goroutine共享该变量
race 竞争检查:(用来检查我们的代码是否存在竞争的情况)
需要注意命令的放置位置:
// 需要注意命令放置的位置
go run -race bank4.go
go build -race bank3.go
竞争检查示例:
F:\github\demo\shareParams\bank4>go run -race bank4.go
begin
= 200
==================
WARNING: DATA RACE
Write at 0x000000639610 by goroutine 8:
main.deposit()
F:/github/demo/shareParams/bank4/bank4.go:38 +0x9c
main.Withdraw()
F:/github/demo/shareParams/bank4/bank4.go:30 +0x75
main.main.func2()
F:/github/demo/shareParams/bank4/bank4.go:52 +0x91
Previous read at 0x000000639610 by goroutine 7:
main.Balance()
F:/github/demo/shareParams/bank4/bank4.go:24 +0x7b
main.main.func1()
F:/github/demo/shareParams/bank4/bank4.go:47 +0x89
Goroutine 8 (running) created at:
main.main()
F:/github/demo/shareParams/bank4/bank4.go:50 +0x176
Goroutine 7 (finished) created at:
main.main()
F:/github/demo/shareParams/bank4/bank4.go:44 +0x10e
==================
取款成功
200
Found 1 data race(s)
exit status 66
本文探讨了解决变量懒加载情况下并发请求导致的数据竞争问题,通过比较使用互斥锁与sync.Once的优劣,并举例展示了如何利用sync.Once简化代码,确保并发安全。同时,提到了race竞争检查的重要性及其实例应用。
1099

被折叠的 条评论
为什么被折叠?



