欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2019年03月11日 10:11:13   作者:hackssssss  
這篇文章主要介紹了golang線程安全的map實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

網(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)題。

基本思路是后臺(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í)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Go語(yǔ)言的IO庫(kù)那么多糾結(jié)該如何選擇

    Go語(yǔ)言的IO庫(kù)那么多糾結(jié)該如何選擇

    在Go語(yǔ)言中涉及 I/O 操作的內(nèi)置庫(kù)有很多種,比如: io 庫(kù), os 庫(kù), ioutil 庫(kù), bufio 庫(kù), bytes 庫(kù), strings 庫(kù)等等。擁有這么多內(nèi)置庫(kù)是好事,但是具體到涉及 I/O 的場(chǎng)景我們應(yīng)該選擇哪個(gè)庫(kù)呢,帶著這個(gè)問(wèn)題一起通過(guò)本文學(xué)習(xí)下吧
    2021-06-06
  • Go語(yǔ)言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器

    Go語(yǔ)言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器

    本文主要介紹了Go語(yǔ)言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • go語(yǔ)言中切片與內(nèi)存復(fù)制 memcpy 的實(shí)現(xiàn)操作

    go語(yǔ)言中切片與內(nèi)存復(fù)制 memcpy 的實(shí)現(xiàn)操作

    這篇文章主要介紹了go語(yǔ)言中切片與內(nèi)存復(fù)制 memcpy 的實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • Go語(yǔ)言面試題之select和channel的用法

    Go語(yǔ)言面試題之select和channel的用法

    金九銀十面試季到了(PS:貌似今年一年都是面試季),就業(yè)環(huán)境很差,導(dǎo)致從業(yè)人員不得不卷。本文將重點(diǎn)講解一下Go面試進(jìn)階知識(shí)點(diǎn)之select和channel,需要的可以參考一下
    2022-09-09
  • Go語(yǔ)言實(shí)現(xiàn)彩色輸出示例詳解

    Go語(yǔ)言實(shí)現(xiàn)彩色輸出示例詳解

    這篇文章主要為大家介紹了Go語(yǔ)言實(shí)現(xiàn)彩色輸出示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Go1.16新特性embed打包靜態(tài)資源文件實(shí)現(xiàn)

    Go1.16新特性embed打包靜態(tài)資源文件實(shí)現(xiàn)

    這篇文章主要為大家介紹了Go?1.16新特性embed打包靜態(tài)資源文件的實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Golang中println和fmt.Println區(qū)別解析

    Golang中println和fmt.Println區(qū)別解析

    Golang 中打印數(shù)據(jù)通常使用 fmt.Println() 方法,也可以使用內(nèi)置的 println() 方法。這兩個(gè)方法大家可能都使用過(guò),它們的區(qū)別是什么呢?本文給大家詳細(xì)講解,感興趣的朋友跟隨小編一起看看吧
    2023-03-03
  • Mac下Vs code配置Go語(yǔ)言環(huán)境的詳細(xì)過(guò)程

    Mac下Vs code配置Go語(yǔ)言環(huán)境的詳細(xì)過(guò)程

    這篇文章給大家介紹Mac下Vs code配置Go語(yǔ)言環(huán)境的詳細(xì)過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-07-07
  • 深入理解Go語(yǔ)言中的結(jié)構(gòu)體

    深入理解Go語(yǔ)言中的結(jié)構(gòu)體

    本文主要介紹了深入理解Go語(yǔ)言中的結(jié)構(gòu)體,包括定義結(jié)構(gòu)體、聲明結(jié)構(gòu)體變量、使用結(jié)構(gòu)體、結(jié)構(gòu)體關(guān)聯(lián)函數(shù)、new、組合等,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11
  • 基于Go語(yǔ)言實(shí)現(xiàn)一個(gè)并發(fā)下載器

    基于Go語(yǔ)言實(shí)現(xiàn)一個(gè)并發(fā)下載器

    這篇文章主要為大家詳細(xì)介紹了如何利用GO語(yǔ)言實(shí)現(xiàn)一個(gè)并發(fā)的文件下載器,可以在不重新啟動(dòng)整個(gè)下載的情況下處理錯(cuò)誤,感興趣的小伙伴可以了解一下
    2023-10-10

最新評(píng)論