網(wǎng)上找的協(xié)程安全的map都是用互斥鎖或者讀寫(xiě)鎖實(shí)現(xiàn)的,這里用單個(gè)協(xié)程來(lái)實(shí)現(xiàn)下,即所有的增刪查改操作都集成到一個(gè)goroutine中,這樣肯定不會(huì)出現(xiàn)多線程并發(fā)訪問(wèn)的問(wèn)題。
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)公司!專(zhuān)注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、成都小程序開(kāi)發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶(hù)創(chuàng)新互聯(lián)還提供了謝家集免費(fèi)建站歡迎大家使用!
基本思路是后臺(tái)啟動(dòng)一個(gè)長(zhǎng)期運(yùn)行的goroutine,阻塞的接受自己channel中的請(qǐng)求req,req分為不同的請(qǐng)求,比如讀key,寫(xiě)key等,然后在這個(gè)goroutine中進(jìn)行各種操作。
例: Get方法向readSig(channel)中發(fā)送一條請(qǐng)求。請(qǐng)求是readReq的指針,當(dāng)run方法接收到信號(hào)時(shí),讀取底層map,將值寫(xiě)入readReq的value中(value是個(gè)channel),Get方法阻塞的接收value,接收到就返回value。
ps:花了兩個(gè)多小時(shí)寫(xiě)完,只是簡(jiǎn)單的做了測(cè)試,沒(méi)有深入測(cè)試,另外性能也沒(méi)有測(cè)過(guò),以后有空會(huì)深入測(cè)試一下正確性以及相比加鎖的寫(xiě)法其性能如何。
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 暫時(shí)先是同步的,異步的可能存在使用方面的問(wèn)題。 } //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
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。