网上找的协程安全的map都是用互斥锁或者读写锁实现的,这里用单个协程来实现下,即所有的增删查改操作都集成到一个goroutine中,这样肯定不会出现多线程并发访问的问题。
基本思路是后台启动一个长期运行的goroutine,阻塞的接受自己channel中的请求req,req分为不同的请求,比如读key,写key等,然后在这个goroutine中进行各种操作。
例: Get方法向readSig(channel)中发送一条请求。请求是readReq的指针,当run方法接收到信号时,读取底层map,将值写入readReq的value中(value是个channel),Get方法阻塞的接收value,接收到就返回value。
ps:花了两个多小时写完,只是简单的做了测试,没有深入测试,另外性能也没有测过,以后有空会深入测试一下正确性以及相比加锁的写法其性能如何。
package util type smap struct { m map[interface{}]interface{} readSig chan *readReq writeSig chan *writeReq lenSig chan *lenReq terminateSig chan bool delSig chan *delReq scanSig chan *scanReq } type readReq struct { key interface{} value interface{} ok chan bool } type writeReq struct { key interface{} value interface{} ok chan bool } type lenReq struct { len chan int } type delReq struct { key interface{} ok chan bool } type scanReq struct { do func(interface{}, interface{}) doWithBreak func(interface{}, interface{}) bool brea int done chan bool } // NewSmap returns an instance of the pointer of safemap func NewSmap() *smap { var mp smap mp.m = make(map[interface{}]interface{}) mp.readSig = make(chan *readReq) mp.writeSig = make(chan *writeReq) mp.lenSig = make(chan *lenReq) mp.delSig = make(chan *delReq) mp.scanSig = make(chan *scanReq) go mp.run() return &mp } //background function to operate map in one goroutine //this can ensure that the map is Concurrent security. func (s *smap) run() { for { select { case read := <-s.readSig: if value, ok := s.m[read.key]; ok { read.value = value read.ok <- true } else { read.ok <- false } case write := <-s.writeSig: s.m[write.key] = write.value write.ok <- true case l := <-s.lenSig: l.len <- len(s.m) case sc := <-s.scanSig: if sc.brea == 0 { for k, v := range s.m { sc.do(k, v) } } else { for k, v := range s.m { ret := sc.doWithBreak(k, v) if ret { break } } } sc.done <- true case d := <-s.delSig: delete(s.m, d.key) d.ok <- true case <-s.terminateSig: return } } } //Get returns the value of key which provided. //if the key not found in map, ok will be false. func (s *smap) Get(key interface{}) (interface{}, bool) { req := &readReq{ key: key, ok: make(chan bool), } s.readSig <- req ok := <-req.ok return req.value, ok } //Set set the key and value to map //ok returns true indicates that key and value is successfully added to map func (s *smap) Set(key interface{}, value interface{}) bool { req := &writeReq{ key: key, value: value, ok: make(chan bool), } s.writeSig <- req return <-req.ok //TODO 暂时先是同步的,异步的可能存在使用方面的问题。 } //Clear clears all the key and value in map. func (s *smap) Clear() { s.m = make(map[interface{}]interface{}) } //Size returns the size of map. func (s *smap) Size() int { req := &lenReq{ len: make(chan int), } s.lenSig <- req return <-req.len } //terminate s.Run function. this function is usually called for debug. //after this do NOT use smap again, because it can make your program block. func (s *smap) TerminateBackGoroutine() { s.terminateSig <- true } //Del delete the key in map func (s *smap) Del(key interface{}) bool { req := &delReq{ key: key, ok: make(chan bool), } s.delSig <- req return <-req.ok } //scan the map. do is a function which operate all of the key and value in map func (s *smap) EachItem(do func(interface{}, interface{})) { req := &scanReq{ do: do, brea: 0, done: make(chan bool), } s.scanSig <- req <-req.done } //scan the map util function 'do' returns true. do is a function which operate all of the key and value in map func (s *smap) EachItemBreak(do func(interface{}, interface{}) bool, condition bool) { req := &scanReq{ doWithBreak: do, brea: 1, done: make(chan bool), } s.scanSig <- req <-req.done } //Exists checks whether the key which provided is exists in map func (s *smap) Exists(key interface{}) bool { if _,found := s.Get(key); found { return true } return false }
github地址:https://github.com/hackssssss/safemap
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件!
如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
暂无“golang线程安全的map实现”评论...
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新动态
2024年11月23日
2024年11月23日
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]