golang Slice和Map并发安全问题
- 多个goroutine对同一个Slice进行写是不安全的。
func main() {
s := []int{}
for i := 0; i < 10000; i++ {
go func(num int) {
s = append(s, num)
}(i)
}
time.Sleep(2 * time.Second)
for i, v := range s { //同时打印索引和值
fmt.Println(i, ":", v)
}
}
打印出来切片的长度小于10000,说明有数据丢失。
通过加锁可以解决:
func main() {
s := []int{}
var mu sync.Mutex
for i := 0; i < 10000; i++ {
go func(num int) {
mu.Lock()
defer mu.Unlock()
s = append(s, num)
}(i)
}
time.Sleep(2 * time.Second)
for i, v := range s { //同时打印索引和值
fmt.Println(i, ":", v)
}
}
- 多个goroutine对同一个map读是安全的
func main() {
m := make(map[int]int)
for i := 0; i < 10000; i++ {
m[i] = i
}
count := 0
for i := 0; i < 10000; i++ {
go func(num int) {
if v, ok := m[num]; ok {
fmt.Println(v)
}
count++
}(i)
}
time.Sleep(2 * time.Second)
fmt.Println(count)
}
- 多个goroutine对同一个map写会panic
func main() {
m := make(map[int]int)
count := 0
for i := 0; i < 10000; i++ {
go func(num int) {
m[num] = num
count++
}(i)
}
time.Sleep(2 * time.Second)
fmt.Println(count)
fmt.Println(len(m))
}
会参数panic错误:fatal error: concurrent map writes
解决方法也是加锁。
- 两个goroutine分别对同一个map进行读和写会panic
func main() {
m := make(map[int]int)
go func() {
for i := 0; i < 10000; i++ {
m[i] = i
}
}()
go func() {
for i := 0; i < 10000; i++ {
if v, ok := m[i]; ok {
fmt.Println(v)
}
}
}()
time.Sleep(2 * time.Second)
fmt.Println(len(m))
}
会报错:fatal error: concurrent map read and map write
需要注意的是并不是所有情况都会报错,测试当i<1000的时候没有报错
通过加锁可以解决:
func main() {
m := make(map[int]int)
var mu sync.Mutex
go func() {
for i := 0; i < 10000; i++ {
mu.Lock()
m[i] = i
fmt.Printf("写入%d\n", i)
mu.Unlock()
}
}()
go func() {
for i := 0; i < 10000; i++ {
mu.Lock()
if v, ok := m[i]; ok {
fmt.Println(v)
}
mu.Unlock()
}
}()
time.Sleep(2 * time.Second)
fmt.Println(len(m))
}
```