golang线程安全地图的实现

  

网上找的协程安全的地图都是用互斥锁或者读写锁实现的,这里用单个协程来实现下,即所有的增删查改操作都集成到一个goroutine中,这样肯定不会出现多线程并发访问的问题。

  

基本思路是后台启动一个长期运行的goroutine,阻塞的接受自己通道中的请求要求,要求分为不同的请求,比如读键,写键等,然后在这个goroutine中进行各种操作。

  

例:方法向readSig(渠道)中发送一条请求。请求是readReq的指针,当运行方法接收到信号时,读取底层地图,将值写入readReq的中值(值是个频道),得到方法阻塞的接收值,接收到就返回价值。

  

ps:花了两个多小时写完,只是简单的做了测试,没有深入测试,另外性能也没有测过,以后有空会深入测试一下正确性以及相比加锁的写法其性能如何。

        包跑龙套      smap struct类型{   米图{}{}][接口界面   readSig陈* readReq   writeSig陈* writeReq   lenSig陈* lenReq   陈terminateSig bool   delSig陈* delReq   scanSig陈* scanReq   }      readReq struct类型{   关键界面{}   价值界面{}   好的陈bool   }      writeReq struct类型{   关键界面{}   价值界面{}   好的陈bool   }      lenReq struct类型{   int len陈   }      delReq struct类型{   关键界面{}   好的陈bool   }      scanReq struct类型{   func(接口界面{},{})   doWithBreak func(接口界面{},{})保龄球   沥青int   做陈bool   }//新闻地图返回safemap的指针的一个实例   func新闻地图()* smap {   var议员smap   mp。m=使(map接口(接口{}){})   mp。readSig=使(陈* readReq)   mp。writeSig=使(陈* writeReq)   mp。lenSig=使(陈* lenReq)   mp.delSig=使(陈* delReq)   mp。scanSig=使(陈* scanReq)   去mp.run ()   返回,议员   }//背景函数操作在一个goroutine地图//这个地图可以确保并发安全。   func (s * smap) run () {   为{   选择{   案例阅读:=& lt; -s.readSig:   如果价值,好的:=s.m [read.key];好{   阅读。值=https://www.yisu.com/zixun/value   阅读。好<-真实   其他}{   阅读。好<-假   }   案例编写:=<-s.writeSig:   s.m[写。关键]=write.value   写。好<-真实   l:=<-s.lenSig:   llen <- len(小)   sc:=<-s.scanSig:   如果sc.brea==0 {   对于k、v:=范围。m {   sc.do (k、v)   }   其他}{   对于k、v:=范围。m {   ret:=sc.doWithBreak (k、v)   如果ret {   打破   }   }   }   sc.done <-真实   例d:=<-s.delSig:   删除(s。米,d.key)   d。好<-真实   情况下<-s.terminateSig:   返回   }   }   }//返回键提供的价值。//如果键中没有地图,好将是错误的。   func (s * smap)得到(关键接口{})(接口{},bool) {   点播:=&readReq {   关键:钥匙,   好:使(陈bool),   }   年代。readSig <-请求   ok:=<-req.ok   返回请求。值,好   }//设置设置映射的键和值//返回true表明,键和值是成功添加到地图   func (s * smap)集({})键界面{},值接口bool {   点播:=&writeReq {   关键:钥匙,   价值:价值,   好:使(陈bool),   }   年代。writeSig <-请求   <要求返回。好吧//TODO暂时先是同步的,异步的可能存在使用方面的问题。   }//清除地图中的所有键和值。   func (s * smap) Clear () {   年代。m=使(map接口(接口{}){})   }//大小返回地图的大小。   int func (s * smap)大小(){   点播:=&lenReq {   len:陈(int),   }   年代。lenSig <-请求   返回<-req.len   }//终止。运行功能。这个函数通常是要求调试。//在此之后又不使用smap,因为它可以让你的程序块。   func (s * smap) TerminateBackGoroutine () {   年代。terminateSig <-真实   }//▽删除地图的关键   func (s * smap)德尔(关键接口{})bool {   点播:=&delReq {   关键:钥匙,   好:使(陈bool),   }   s.delSig <-请求   返回<-req.ok   }//扫描地图。做的是一个函数的操作中所有的键和值地图吗   func (s * smap) EachItem (func(接口界面{},{})){   点播:=&scanReq {   做的事:做什么,   沥青:0,   做:让(陈bool),   }   年代。scanSig <-请求   <-req.done   }//扫描地图util听函数返回true。做的是一个函数的操作中所有的键和值地图吗   func (s * smap) EachItemBreak(做func(接口界面{},{})bool,条件bool) {   点播:=,scanReq {   doWithBreak:,   沥青:1、   做:让(陈bool),   }   年代。scanSig & lt;——要求   & lt; -req.done   }//检查是否存在提供的关键是存在于地图上   func (s * smap)存在(关键接口{})bool {   如果_,发现:=s.Get(关键);发现{   还真   }   返回假   }

golang线程安全地图的实现