# #multithreading #go #pointers #slice #goroutine
Вопрос:
Вот код:
var timePointer *[]time.Time
func UpdateHolidayList() error {
//updating logic: pulling list of holidays from API
holidaySlice := make([]time.Time, 0)
//appending some holidays of type time.Time to holidaySlice
//now holidaySlice contains a few time.Time values
timePointer = amp;holidaySlice
return nil
}
func main() {
//run UpdateHoliday every 7 days
go func() {
for {
UpdateHoliday()
time.Sleep(7 * 3600 * time.Hour)
}
}()
}
У меня есть 4 вопроса:
holidaySlice
является ли локальная переменная, безопасно ли указывать на нее (глобальный) указатель?- Безопасен ли весь этот многопоточный код?
- После указания
timePointer
наholidaySlice
, могу ли я получить доступ к значениям черезtimePointer
- (Если ответ на 3. «да») Список праздников постоянно меняется, поэтому
holidaySlice
каждое обновление будет отличаться. Изменятся ли тогда значения, доступные черезtimePointer
, соответствующим образом?
Ответ №1:
holidaySlice
является локальной переменной, выделенной в куче. Любая переменная, указывающая на одно и то же расположение кучи, может получить доступ к структуре данных в этом месте. Является ли он безопасным или нет, зависит от того, как вы получите к нему доступ. Даже если holidaySlice
он явно не был выделен в куче, как только вы укажете на него глобальную переменную, компилятор Go обнаружит, что она «ускользает», поэтому он выделит ее в куче.
Код не является потокобезопасным. Вы изменяете общую переменную (глобальную переменную) без какой-либо явной синхронизации, поэтому нет никакой гарантии, когда или если другие городские службы увидят обновления этой переменной.
Если вы обновляете содержимое timePointer
массива без явной синхронизации, нет никакой гарантии, когда или если другие городские сети увидят эти обновления. Вы должны использовать примитивы синхронизации, например sync/Mutex
, для ограничения доступа на чтение/запись к структурам данных, которые могут быть обновлены/прочитаны несколькими линиями.
Ответ №2:
- До тех пор, пока ваш основной не закончится
timePointer
, у вас будет доступ к указателю, которыйholidaySlice
создает — поскольку его куча выделена, компилятор обнаружит его побег и не освободит память. - Нет, абсолютно нет. Посмотрите на пакет синхронизации
- Да, ты можешь. Просто не забудьте повторить, используя
*timePointer
вместоtimePointer
- Это изменится — но не соответствующим образом. Поскольку вы не выполнили никакой синхронизации — у вас нет определенного способа узнать, какие данные хранятся в срезе, на который указывает,
timePointer
когда они считываются.