В sync.Map необходимо использовать Load, а затем LoadOrStore для сложных значений - PullRequest
0 голосов
/ 29 июня 2018

В коде, где глобальная карта с дорогой для генерации структуры значений может быть изменена несколькими параллельными потоками, какой шаблон является правильным?

// 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?

1 Ответ

0 голосов
/ 29 июня 2018

Вариант 1, очевидно, может быть вызван несколькими программами одновременно с новым ip, и только последний в блоке if будет сохранен. Эта возможность значительно увеличивается при увеличении длительности buildComplexActivityObject, поскольку в критическом разделе больше времени.

Вариант 2 работает, но каждый раз вызывает buildComplexActivityObject, что, как вы заявляете, не то, что вы хотите.

Учитывая, что вы хотите вызывать buildComplexActivityObject как можно реже, третий вариант является единственным, который имеет смысл.

Однако sync.Map не может защитить действительные значения activity, на которые ссылаются сохраненные указатели. Там также нужна синхронизация при обновлении значения activity.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...