Sobes.tech
Назад к вопросам
Senior
1

Являются ли слайсы в Go потокобезопасными? Можно ли писать в разные индексы слайса параллельно без мьютекса?

Компании, где спрашивали
2gis2gis

Ответ от нейросети

sobes.tech AI

Слайсы в Go сами по себе не являются потокобезопасными. Это связано с тем, что слайс — это структура, содержащая указатель на массив, длину и емкость. При параллельном доступе к разным индексам слайса без синхронизации возможны гонки данных, если одновременно происходит изменение структуры слайса (например, расширение слайса, изменение длины).

Если вы гарантируете, что слайс не меняет свою длину и емкость, и параллельно пишете в разные индексы, которые не пересекаются, то в теории это безопасно, так как разные элементы массива — разные области памяти. Однако это требует строгого контроля и понимания, что никто не изменяет слайс (например, не вызывает append).

Резюмируя:

  • Чтение и запись в разные индексы массива, на который ссылается слайс, могут быть безопасны без мьютекса, если длина и емкость не меняются.
  • Любые операции, изменяющие структуру слайса (append, срезы, изменение длины), требуют синхронизации.
  • Для гарантированной потокобезопасности лучше использовать мьютексы или другие механизмы синхронизации.

Пример безопасной параллельной записи в разные индексы массива:

package main

import (
	"fmt"
	"sync"
)

func main() {
	arr := make([]int, 10)
	var wg sync.WaitGroup

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			arr[i] = i * i // безопасно, разные индексы
		}(i)
	}

	wg.Wait()
	fmt.Println(arr)
}

Но если вы будете менять длину слайса или делать append, то без синхронизации возможны гонки.