В этом фрагменте кода запускается горутина, которая многократно увеличивает переменную i:
package main
import "time"
func main() {
i := 1
go func() {
for {
i
}
}()
Однако результат всегда равен 1. Такое поведение можно отнести к модели памяти Go и конкретной реализации этого кода.
Модель памяти Go
The Модель памяти Go определяет условия, при которых при чтении переменной в одной горутине можно гарантированно наблюдать значения, полученные при записи в ту же переменную в другой горутине. Он подчеркивает важность синхронизации для одновременного доступа к общим данным.
Пропуск синхронизации
В данном коде:
- Присваивание i (т.е. i ) не сопровождается каким-либо событием синхронизации, что указывает на то, что изменения могут быть не сразу видны другим горутинам.
- Компилятор может оптимизировать эту оптимизацию цикла, упростив ее до неактивного режима.
Оптимизация компилятором
Агрессивный компилятор может удалить оператор i, эффективно сокращая горутину до:
for {}
Пример с синхронизацией
Чтобы продемонстрировать, что проблема связана с отсутствием синхронизации, рассмотрим следующий код:
package main
import (
"sync"
"time"
)
func main() {
mx := new(sync.Mutex)
i := 1
go func() {
for {
mx.Lock()
i
mx.Unlock()
}
}()
В этом случае на выходе будет уже не 1, а большое число, как и ожидалось. sync.Mutex обеспечивает синхронизацию и гарантирует, что обе горутины получают контролируемый доступ к i, позволяя горутине увеличивать i и делая изменения видимыми для основной подпрограммы.
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3