dora0817 2018-06-29 14:08
浏览 630
已采纳

在sync.Map中,必须对复杂值使用Load和LoadOrStore

In code where a global map with an expensive to generate value structure may be modified by multiple concurrent threads, which pattern is correct?

// 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)
}

Is version three the correct pattern given Go's concurrency model?

  • 写回答

1条回答 默认 最新

  • doujishao8793 2018-06-29 14:37
    关注

    Option 1 obviously can be called by multiple goroutines with a new ip concurrently, and only the last one in the if block would get stored. This possibility is greatly increased the longer buildComplexActivityObject takes, as there is more time in the critical section.

    Option 2 works, but calls buildComplexActivityObject every time, which you state is not what you want.

    Given that you want to call buildComplexActivityObject as infrequently as possible, the third option is the only one that makes sense.

    The sync.Map however cannot protect the actual activity values referenced by the stored pointers. You also need synchronization there when updating the activity value.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 制裁名单20240508芯片厂商
  • ¥20 易康econgnition精度验证
  • ¥15 线程问题判断多次进入
  • ¥15 msix packaging tool打包问题
  • ¥28 微信小程序开发页面布局没问题,真机调试的时候页面布局就乱了
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接