首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在sync.Map中,是否有必要对复杂的值使用Load,后面跟着LoadOrStore

在sync.Map中,是否有必要对复杂的值使用Load,后面跟着LoadOrStore
EN

Stack Overflow用户
提问于 2018-06-29 14:08:15
回答 1查看 553关注 0票数 3

在具有昂贵的值结构的全局映射可能被多个并发线程修改的代码中,哪种模式是正确的?

代码语言:javascript
复制
// equivalent to map[string]*activity where activity is a
// fairly heavyweight structure
var ipActivity sync.Map

// version 1: not safe with multiple threads, I think
func incrementIP(ip string) {
  val, ok := ipActivity.Load(ip)
  if !ok {
    val = buildComplexActivityObject()
    ipActivity.Store(ip, val)
  }

  updateTheActivityObject(val.(*activity), ip)
}

// version 2: inefficient, I think, because a complex object is built 
// every time even through it's only needed the first time
func incrementIP(ip string) {
  tmp := buildComplexActivityObject()
  val, _ := ipActivity.LoadOrStore(ip, tmp)
  updateTheActivity(val.(*activity), ip)
}

// version 3: more complex but technically correct?
func incrementIP(ip string) {
  val, found := ipActivity.Load(ip)
  if !found {
     tmp := buildComplexActivityObject()

     // using load or store incase the mapping was already made in 
     // another store
     val, _ = ipActivity.LoadOrStore(ip, tmp)
  }
  updateTheActivity(val.(*activity), ip)
}

第三版是否正确的模式给出了Go的并发模型?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-29 14:37:08

选项1显然可以由具有新ip的多个goroutines同时调用,并且只有if块中的最后一个将被存储。这种可能性随着buildComplexActivityObject时间的延长而大大增加,因为关键部分有更多的时间。

选项2有效,但每次都调用buildComplexActivityObject,这不是您想要的结果。

考虑到您希望尽可能频繁地调用buildComplexActivityObject,第三个选项是唯一有意义的选项。

但是,sync.Map不能保护存储指针引用的实际activity值。更新activity值时,还需要同步。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51103621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档