Во-первых, некоторые Go терминологии:
[]int{1, 2, 3}
является ломтик, не массив. Массив будет записан как [...]int{1, 2, 3}
.
Кусочек триплет (start, length, capacity)
и указывает на базовый массив (обычно кучного выделено, но это деталь реализации, что язык полностью скрывает от вас!)
модель памяти Go позволяет любое количество читателей или (но не и) не более одного писателя в любой заданный регион в памяти. Go memory model (к сожалению) конкретно не вызывает случай одновременного доступа к нескольким индексам в один и тот же срез, но, как представляется, это нормально (т. Е. Они рассматриваются как разные места в памяти, как и следовало ожидать).
Так что, если вы просто читаете оттуда, нет необходимости защищать его вообще.
Если вы читаете и писать к нему, но goroutines не читать и писать в одних и тех же местах, как друг с другом (например, если goroutine i
только считывает и записывает в положение i
), то вы также не требуется синхронизация. Кроме того, вы можете либо синхронизировать весь фрагмент (что означает меньшее количество мьютексов, но много), или вы могли бы синхронизировать отдельные позиции в срезе (что означает гораздо более низкую конкуренцию, но многие другие мьютексы и блокировки были приобретены и выпущены).
Но поскольку Go позволяет функции захвата переменных в объеме (то есть, они являются замыканиями) там действительно нет причин, чтобы передать массив в качестве указателя на всех:
Ваш код будет, таким образом, наиболее идиоматически быть записана в виде :
a := []int{1,2,3}
for i := 0; i < 10; i++
for i < 10 {
go func() {
for _, i := range a {
fmt.Println(a[0])
}
}()
}
Я не совсем уверен, что приведенный выше код должен быть для-, так как он собирается распечатать a[0]
10 раз в различных goroutines, что делает его похожим на это даже не используя кусочек в осмысленно.
Условное объяснение. Благодаря! Код является всего лишь примером, поэтому я могу понять, как работают указатели, массивы и блокировки. Кажется, я часто сталкиваюсь с этим конкретным шаблоном. В любом случае, еще раз спасибо. – Soubriquet
Одно из предостережений заключается в том, что существует распространенная ошибка (которая обнаруживает 'go vet', поэтому я бы рекомендовал работать) состоит в том, что переменные цикла (например,' i' в 'range') имеют область, которая длится дольше, чем заданная итерация ; в частности: 'для i: = диапазон a {go func() {fmt.Printf ("% d ", i)}()}' , вероятно, распечатает 3, 3, 3 или различные другие значения поскольку все горуты захватывают один и тот же «i». Решение состоит в том, чтобы сделать 'для i: = range a {go func (i int) {fmt.Printf ("% d ", i)} (i)}' – TaslemGuy
Что значит, что они длятся дольше? Они все еще только в области цикла, верно? – Soubriquet