问题:我们在日常业务开发的时候肯定会用到协程,大部分为了提高整个功能的执行速率,当遇到多个协程并发读写map时大家肯定遇到过一些问题~
先举例一个错误示范:
// 错误示范
package main
import (
"fmt"
"time"
)
func main() {
m := make(map[int]int)
go func() { //协程1
for {
read := m[1] //并发读
fmt.Println("read -> ", read)
}
}()
go func() { //协程2
for {
m[1] = 10 // 并发写
fmt.Println("m -> ", m)
}
}()
time.Sleep(100*time.Second)
}
上述代码将会出现bug/panic的问题,我在运行过程中就会出现Panic 的问题~
Go 协程并发安全使用map的方式:
1、先看看我们通过加锁的方式进行:
// 加锁的方式
package main
import (
"fmt"
"sync"
"time"
)
func main() {
m := make(map[int]int)
l := sync.Mutex{}
go func() { //协程1
for {
l.Lock()
read := m[1] //并发读
fmt.Println("read -> ", read)
l.Unlock()
}
}()
go func() { //协程2
for {
l.Lock()
m[1] = 10 // 并发写
fmt.Println("m -> ", m)
l.Unlock()
}
}()
time.Sleep(10*time.Second)
}
2、Go 1.9 版本以后官方给出了sync.Map 同步map(基于锁);
package main
import (
"fmt"
"sync"
"time"
)
func main() {
m := sync.Map{}
i := 1
go func() { //协程1
for {
read, ok := m.Load("1") //并发读
if ok {
fmt.Println("read -> ", read)
} else {
fmt.Println("read -> ", "X")
}
}
}()
go func() { //协程2
for {
m.Store("1", i) // 并发写
i++
}
}()
time.Sleep(10*time.Second)
}