• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    golang线程安全的map实现

    网上找的协程安全的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

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    您可能感兴趣的文章:
    • Golang Map实现赋值和扩容的示例代码
    • golang中range在slice和map遍历中的注意事项
    • golang 并发安全Map以及分段锁的实现方法
    • Golang实现对map的并发读写的方法示例
    • golang中sync.Map并发创建、读取问题实战记录
    • golang如何实现mapreduce单进程版本详解
    • Golang map如何生成有序的json数据详解
    • golang针对map的判断,删除操作示例
    • 理解Golang中的数组(array)、切片(slice)和map
    • Golang 使用map需要注意的几个点
    上一篇:golang高并发的深入理解
    下一篇:Golang实现对map的并发读写的方法示例
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    golang线程安全的map实现 golang,线程,安全,的,map,实现,