вопрос о бесконечности цикла и распределении памяти - PullRequest
0 голосов
/ 31 октября 2019

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

func main() {
    runtime.GOMAXPROCS(2)
    go func() {
        for {
            //fmt.Printf("goroutine1\n")
        }
    }()
    fmt.Println("main thread1")
    x := [1145][1145]int{}
    for i := 0; i < 1144; i++ {
        fmt.Println(i)
        x[i][i] = i
    }
    fmt.Println("main thread2")

}

если я ничего не делаю в бесконечном цикле, мой основной поток1 никогда не сможет успешно выделить память и напечатать «основной поток2», даже если я установлю GOMAXPROCS на 2, если я напечатаю что-то внутри бесконечного цикла,все работает нормально (что ожидается, так как программа распечатывает что-то в бесконечном цикле, она вызывает системный вызов и выдает процессор, поэтому мой основной поток может выделить память.

Мне интересно, почему это так?

1 Ответ

0 голосов
/ 31 октября 2019

В вашей базовой компьютерной системе есть несколько исполнителей потоков. Среда выполнения Go сама определяет, сколько из них, и создает соответствующее количество исполнителей среды выполнения, чтобы использовать все системы. Изменение GOMAXPROCS изменяет количество исполнителей, которые попытается выделить среда выполнения, но не влияет на базовую систему. В этом случае, похоже, что у самой базовой системы есть только один исполнитель.

Если бы у вашей базовой системы было два или более, Go уже к этому моменту создал бы двух исполнителей и запустил бы программу бесконечного цикла наодин из них, и ваша main программа на другом, в то же время. Но поскольку ваша система имеет только один, запускается только один. Независимо от того, сколько исполнителей уровня времени выполнения может создать среда выполнения Go, только один из них может быть привязан к аппаратному ЦП для фактического запуска .

Обратите внимание, что подпрограммы отображаются на многиеН. Например, предположим, что вы выполнили 1000 подпрограмм и имеете десять процессоров. Среда выполнения выделит десять исполнителей и использует десять процессоров для одновременного запуска десяти из 1000 подпрограмм. Оставшиеся 990 программ ожидают, пока один из исполнителей не достигнет точки, когда он добровольно прекращает выполнение этой программы и подбирает одну из оставшихся 990.

Вы можете позвонить runtime.Gosched Вы сами, из любой программы, скажете: Я добровольно отстраиваюсь, чтобы другие программы, которые хотели бы запускаться, работали, пока исполнитель не сможет забрать меня для запуска. Многие другие системы вызывают этофункция yield или какой-то вариант. (И будьте осторожны со словом «приостановить»: я использовал его здесь для эффекта, но процедура, вызвавшая runtime.Gosched, технически не приостановлена ​​ в том смысле, что она все еще помечена как «хотела бы работать», в то время какдругие goroutines могут быть технически приостановлены в том смысле, что они помечены как «не может работать сейчас, ожидая ____» (заполните пробел).)

См. также Как работают goroutines? (или: отношение goroutines и потоков ОС) .

...