佳木斯湛栽影视文化发展公司

主頁(yè) > 知識(shí)庫(kù) > golang線程安全的map實(shí)現(xiàn)

golang線程安全的map實(shí)現(xiàn)

熱門標(biāo)簽:Linux服務(wù)器 百度競(jìng)價(jià)排名 呼叫中心市場(chǎng)需求 鐵路電話系統(tǒng) 地方門戶網(wǎng)站 服務(wù)外包 AI電銷 網(wǎng)站排名優(yōu)化

網(wǎng)上找的協(xié)程安全的map都是用互斥鎖或者讀寫鎖實(shí)現(xiàn)的,這里用單個(gè)協(xié)程來(lái)實(shí)現(xiàn)下,即所有的增刪查改操作都集成到一個(gè)goroutine中,這樣肯定不會(huì)出現(xiàn)多線程并發(fā)訪問(wèn)的問(wèn)題。

基本思路是后臺(tái)啟動(dòng)一個(gè)長(zhǎng)期運(yùn)行的goroutine,阻塞的接受自己channel中的請(qǐng)求req,req分為不同的請(qǐng)求,比如讀key,寫key等,然后在這個(gè)goroutine中進(jìn)行各種操作。

例: Get方法向readSig(channel)中發(fā)送一條請(qǐng)求。請(qǐng)求是readReq的指針,當(dāng)run方法接收到信號(hào)時(shí),讀取底層map,將值寫入readReq的value中(value是個(gè)channel),Get方法阻塞的接收value,接收到就返回value。

ps:花了兩個(gè)多小時(shí)寫完,只是簡(jiǎn)單的做了測(cè)試,沒(méi)有深入測(cè)試,另外性能也沒(méi)有測(cè)過(guò),以后有空會(huì)深入測(cè)試一下正確性以及相比加鎖的寫法其性能如何。

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í)有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:
  • Golang Map實(shí)現(xiàn)賦值和擴(kuò)容的示例代碼
  • golang中range在slice和map遍歷中的注意事項(xiàng)
  • golang 并發(fā)安全Map以及分段鎖的實(shí)現(xiàn)方法
  • Golang實(shí)現(xiàn)對(duì)map的并發(fā)讀寫的方法示例
  • golang中sync.Map并發(fā)創(chuàng)建、讀取問(wèn)題實(shí)戰(zhàn)記錄
  • golang如何實(shí)現(xiàn)mapreduce單進(jìn)程版本詳解
  • Golang map如何生成有序的json數(shù)據(jù)詳解
  • golang針對(duì)map的判斷,刪除操作示例
  • 理解Golang中的數(shù)組(array)、切片(slice)和map
  • Golang 使用map需要注意的幾個(gè)點(diǎn)

標(biāo)簽:蘭州 黃山 崇左 湘潭 仙桃 衡水 銅川 湖南

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《golang線程安全的map實(shí)現(xiàn)》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    博野县| 瓮安县| 巩义市| 乌拉特中旗| 大理市| 阿鲁科尔沁旗| 乌兰县| 呼图壁县| 赤城县| 阿克| 大城县| 简阳市| 定南县| 榆树市| 云龙县| 洪湖市| 正镶白旗| 康定县| 农安县| 微山县| 福泉市| 垣曲县| 平顶山市| 玛曲县| 鄱阳县| 公安县| 盘锦市| 滁州市| 将乐县| 桂平市| 大方县| 南溪县| 清远市| 屏南县| 沭阳县| 舒兰市| 贵南县| 舞阳县| 江川县| 巨鹿县| 汪清县|