1.单例模式误区
Go语言无法完美支持单例模式
现在我们是在并发的情况下去调用的 GetInstance函数,现在恰好第一个goroutine执行到m = &Manager {}这句话之前,第二个goroutine也来获取实例了,第二个goroutine去判断m是不是nil,因为m = &Manager{}还没有来得及执行,所以m肯定是nil,现在出现的问题就是if中的语句可能会执行两遍!
代码做了简单的修改了,引入了锁的机制,在GetInstance函数中,每次调用我们都会上一把锁,保证只有一个goroutine执行它,这个时候并发的问题就解决了。不过现在不管什么情况下都会上一把锁,而且加锁的代价是很大的,有没有办法继续对我们的代码进行进一步的优化呢? 熟悉java的同学可能早就想到了双重的概念,没错,在go中我们也可以使用双重锁机制来提高效率。
就是我们的sync.Once
,它有一个Do方法,在它中的函数go会只保证仅仅调用一次!再次修改我们的代码,
2.对于原有程序优化
但是运行后程序还是出问题map读写出问题并发导致冲突
解决方法
锁是必须加的map读写,对于多个IO某一个在读序列号并存储另一个IO在写入序列号会导致并发map
3.思考对于map使用锁还是sync.Map来处理
Sync.Map开箱取值为接口—使用接口断言来取值复杂性提高,同时对json支持不友好
对于加锁和结构体对象选择--------选择结构体对象来访问而不选择加锁
对于sync.Map到底使用不使用?
不推荐使用sync.Map那么如何使用map并安全并发…………………结构体包裹锁与map
4.合理的使用结构体map对象防止并发问题,最好不要单独使用map全局变量
5.go语言三层map嵌套处理逻辑
package main
import (
"fmt"
"strings"
"time"
)
var channel chan string
var mqttmsgstationmap map[string]map[string]map[string]string //三层嵌套.....
func main() {
mqttmsgstationmap = make(map[string]map[string]map[string]string)//字典必须初始化
channel = make(chan string, 100)//缓存channel
channel <- "11111" + "|" + "@@@" + "|" + "++++"+ "|" +"!!!!"
channel <- "11111" + "|" + "@@@" + "|" + "1111"+ "|" +"!!!!"
channel <- "22222" + "|" + "^^^" + "|" + "++++"+ "|" +"!!!!"
channel <- "22222" + "|" + "***" + "|" + "1111"+ "|" +"!!!!"
channel <- "33333" + "|" + "$$$" + "|" + "++++"+ "|" +"!!!!"
channel <- "44444" + "|" + "###" + "|" + "1111"+ "|" +"!!!!"
go test()
time.Sleep(time.Second)
fmt.Println(mqttmsgstationmap)
for ; ; {
time.Sleep(time.Second)
}
}
func test() {
for {
select {
case msg := <-channel:
tempmsg := strings.Split(msg, "|")
if len(tempmsg) == 4 {
tmpMap := mqttmsgstationmap[tempmsg[0]] //
fmt.Printf("%p\n", &tmpMap)
if tmpMap == nil {
tmpMap = make(map[string]map[string]string)
atomm:=mqttmsgstationmap[tempmsg[0]][tempmsg[1]]
if atomm==nil{
atomm=make(map[string]string)
atomm[tempmsg[2]]=tempmsg[3]
tmpMap [tempmsg[1]] = atomm
}
}else{//二层
atomm:=mqttmsgstationmap[tempmsg[0]][tempmsg[1]]
if atomm==nil{
atomm=make(map[string]string)
atomm[tempmsg[2]]=tempmsg[3]
tmpMap [tempmsg[1]] = atomm
}else{
atomm[tempmsg[2]]=tempmsg[3]
tmpMap [tempmsg[1]] = atomm
}
}
mqttmsgstationmap[tempmsg[0]] = tmpMap//存入一组map释放空间
}
}
}
}
Python下多层字典嵌套:
New_list = [['key1', 'value1', 'ss','11'], ['key2', 'value2', 'pp','22'], ['key3', 'value3', 'vv','33']]
# 那么对于三维列表可以这样来分离
ss={}
for x in New_list:
if x[0] not in ss:
ss[x[0]]={}#分配空间
if x[1] not in ss[x[0]]:
ss[x[0]][x[1]]={}
ss[x[0]][x[1]][x[2]]=x[3]
print(ss)
代码逻辑更加清晰
6.系统资源竞争工具的使用
go run -race XXX.go