Go игнорирует GOMAXPROCS

Я пытаюсь запустить горутину (версия go1.4.1 darwin/amd64) одновременно с бесконечным циклом в основном потоке, и я не могу заставить ее работать. Если я правильно понял, go должен запланировать горутину для других потоков, если я укажу GOMAXPROCS, но этого не произойдет. Даже если я явно напишу LockOSThread() в main, я все равно не увижу вывода. Как запустить горутину в отдельном потоке ОС?

package main

import(
    "fmt"
    "time"
    "runtime"
)

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU() * 8)

    go func() {
        for {
            time.Sleep(1 * time.Second)
            fmt.Println("From routine")
        }
    }()

    for {}
}

person Alexey Kutuzov    schedule 23.02.2015    source источник
comment
Я думаю, что проблема здесь в том, что новая горутина еще не создана (поэтому ее нельзя запланировать), когда вы вводите for{} . Планировщик может работать только тогда, когда горутина заблокирована или вызывает другую функцию, поэтому в замкнутом цикле планировщик не может планировать. Добавьте time.Sleep(time.Millisecond) перед for{}, и это сработает.   -  person siritinga    schedule 23.02.2015
comment
@siritinga да, это помогает. Спасибо. Пожалуйста, сделайте ответ, чтобы я мог принять его.   -  person Alexey Kutuzov    schedule 23.02.2015


Ответы (1)


Проблема в том, что новая горутина еще не создана (поэтому ее нельзя запланировать), когда вы вводите for{}. Планировщик может работать только тогда, когда горутина заблокирована или вызывает другую функцию, поэтому в замкнутом цикле планировщик не может планировать.

Добавьте time.Sleep(time.Millisecond) перед for{} и все заработает.

Тем не менее, я не знаю, делаете ли вы это просто для развлечения, но если вы хотите ждать вечно (или до тех пор, пока другие горунти не заблокируются или не умрут), пока работают горутины, гораздо лучше использовать select{}, который будет блокировать, не тратя впустую циклы процессора.

person siritinga    schedule 23.02.2015
comment
Лучше, чем time.Sleep, будет runtime.Gosched. - person Dave C; 23.02.2015
comment
Я пробовал это, Дэйв, но кажется, что примерно в 10% случаев планировщик снова запустит main до того, как будет создана горутина (проверено на Go1.4.2 и Raspberry Pi). Конечно, лучшим решением было бы использовать каналы или группу ожидания, чтобы сообщить основной горутине, что новая горутина активна. - person siritinga; 23.02.2015