Go语言map的并发操作

先单独说一下map,在Go语言中,map与通道类似,都需要先用make函数进行初始化,之后才可以赋值,不过map没有长度的限制,所以在使用make函数初始化map时,make函数的第二个参数不用写,写不写没有区别。

package main

import "fmt"

func main() {
	var m map[int]int
	//m = make(map[int]int,20)
	m[22] = 10
	fmt.Println(len(m))
}

运行结果

panic: assignment to entry in nil map

goroutine 1 [running]:
main.main()

错误原因,赋值给空map。

package main

import "fmt"

func main() {
	var m map[int]int
	m = make(map[int]int,20)
	m[22] = 10
	fmt.Println(len(m))
}

用make函数初始化map时,make的第二个参数写上也没有意义。

map在并发中

Go语言中map不是并发安全的,map不可以并发的写,但是可以并发的读。

package main

import (
	"fmt"
	"sync"
)

func main() {
	wg := sync.WaitGroup{}
	m := make(map[int]int)
	const N = 20

	wg.Add(N)

	for i := 0; i < N; i++ {
		go func() {
			defer wg.Done()
			m[i] = i
		}()
	}
	wg.Wait()
	fmt.Println(len(m))
	fmt.Println(m)
}

运行结果

fatal error: concurrent map writes

goroutine 7 [running]:
runtime.throw(0x10c4e4d, 0x15)

map在goroutine中并发写的时候不是线程安全的,所以不加锁会报错。
加锁后才可以并发写入

mu.Lock()
defer wg.Done()
m[i] = i
mu.Unlock()

不用加锁,可以并发读取

package main

import (
	"fmt"
	"sync"
)

func main() {
	wg := sync.WaitGroup{}
	m := make(map[int]int)
	const N = 20
	for i := 0; i < N; i++ {
		m[i] = i
	}

	wg.Add(N)
	for i := 0; i < N; i++ {
		go func(n int) {
			fmt.Print(m[n],"\t")
			wg.Done()
		}(i)
	}
	wg.Wait()
	fmt.Println("\n")
	fmt.Println(m)
	fmt.Println(len(m))
}

运行结果

19	6	7	8	9	10	11	12	13	14	15	16	17	18	5	3	4	0	2	1	

map[6:6 10:10 11:11 15:15 17:17 1:1 2:2 4:4 7:7 8:8 16:16 0:0 3:3 9:9 19:19 5:5 12:12 13:13 14:14 18:18]
20

猜你喜欢

转载自blog.csdn.net/Charliewolf/article/details/84936637