2017-01-06 2 views
3

Я изучаю о golang.goroutine один процесс ошибка в golang

В golang есть концепция, называемая goroutine. Я пишу пример кода.

package main 

import (
    "fmt" 
    "runtime" 
) 

func main() { 
    runtime.GOMAXPROCS(1) // cpu core를 하나만 사용하도록 해 놓음 

    s := "test string" 

    for i := 0; i < 100; i++ { 
     go func(n int) { 
      fmt.Println(s, n) 
     }(i) 
    } 

    fmt.Scanln() 
} 

если вы интерпретировать код и запускать, вы увидите первые данные печати

тест Строка 99

Я не знаю, почему это приведет. Кто-нибудь мне помогает?

+0

Похоже, что код выводит строки можно было ожидать: https://play.golang.org/p/54IP16NQZu При работе с потоками и goroutines порядок выполнения не гарантируется, поэтому они могут распечатываться в любом порядке, и это было бы действительно. – Omar

+0

в результате для моего кода проблема была в первых данных - это последние данные, которые не должны быть вызваны. другие печатные данные являются нормальными, за исключением первых данных. поэтому у меня есть вопрос. но я понял после чтения в 2 ответа. Спасибо за ваш комментарий. –

ответ

3

Именно из-за этой линии:

runtime.GOMAXPROCS(1) 

Как goroutine это способ выполнения кода одновременно, все goroutine вы создаете в цикле придется ждать прока.

Поскольку у вас есть только один, и он занят выполнением цикла, у вас будет стек goroutine.

Когда петли заканчиваются, у proc есть время, чтобы выполнить первый горутин, который был последним создан, а затем сделать то же самое с стеком один за другим, но на этот раз в последовательности.

Попробуйте поместить Просы и посмотрите, что будет.

Имейте в виду, что при одновременном выполнении заказа, в котором выполняется код, не гарантируется, как уже упоминалось в комментарии.

Здесь у вас есть последовательность, только потому, что у вас есть только один процесс.

Если ваша цель состоит в том, чтобы элементы обрабатывались последовательно даже в параллельном режиме, вы должны использовать каналы.

Позвольте мне показать образец кода, сделать работу:

пакет главный

import (
    "fmt" 
    "runtime" 
) 

func printNumbers(text string, ns chan int) { 
    for n := range ns { 
     fmt.Println(text, n) 
    } 
} 

func main() { 
    runtime.GOMAXPROCS(1) // cpu core를 하나만 사용하도록 해 놓음 

    s := "test string" 

    numbers := make(chan int) 

    go printNumbers(s, numbers) 

    go func() { 
     for i := 0; i < 100; i++ { 
      numbers <- i 
     } 
     close(numbers) 
    }() 

    fmt.Scanln() 
} 

Как вы можете видеть, это просто новая версия вашего, но если вы выполняете, вы должны получить надлежащее последовательность.

Основные изменения состоят в том, что теперь у вас есть 2 goroutine, один для печати и один для цикла.

2 goroutine talk throungh канал int.

Когда программа запускает первый вызов goroutin, функция printNumbers, что stai ждет, пока что-то не будет записано в канал.

Затем запустите второй поворот, который записывает по одному целые числа в канал.

После того, как закончен, как только у вас есть только 1 процесс, функция printNumbers запускается снова, так как есть предметы внутри канала.

Это петли, пока не закончится itmes.

Конечно, у вас здесь 2 петли, но вы не можете этого избежать.

Итак, теперь попробуйте ослабить процесс, как вы пожелаете, и посмотрите, что произойдет.

+0

Хм. этот код предназначен мне. потому что я хочу ожидать последовательного результата. поэтому, я не думаю, что код не участвует в проблеме. Если этот код удаляется, вывод не является последовательным, как вы сказали, из-за использования mulit-core –

+0

спасибо, но я намерен использовать один процессор процесса и ожидать последовательного результата, не используя канал. хм .. я понимаю, что вы скажете. поэтому я ценю. ваше объяснение имеет смысл для меня, как для другого мышления. Я думаю, что более близко ответят. Я думаю, что это связано с планированием. Еще раз спасибо за ваш ответ –

+0

В качестве ссылки, до Go lang 1.4, goroutine работает последовательно. но более 1,5 не имеет гарантии для последовательности удаления горутина. Будьте ссылкой. ^^ –

0

Ваш вопрос хороший, и ответ в основном о том, как работает внутренняя среда выполнения Go Scheduler, но, поскольку Марио Сантини говорит, что порядок исполнения не является гарантией.

В моих ограниченных словах я могу сказать вам, что планировщик Go зависит от того, какой алгоритм планировщика процесса https://en.wikipedia.org/wiki/Scheduling_(computing) используется внутренне и на основании этого он будет решать, сколько времени выполнено и порядок каждого горутинга, требующего запуска, также он будет создавать потоки ОС для вас по мере необходимости, в вашем случае вы ограничиваете только 1, так что это будет не parallel, так что, очевидно, последний goroutine становится достаточно удачным, чтобы запустить его как первый.

Я оставляю вам несколько ссылок с лучшими объяснениями:

https://www.quora.com/How-does-the-golang-scheduler-workhttp://www.sarathlakshman.com/2016/06/15/pitfall-of-golang-schedulerhttp://www.slideshare.net/matthewrdale/demystifying-the-go-scheduler

+0

Хорошо, когда я сказал, что «последовательность выполнения не является гарантией» - это именно то, что объясняет, почему она выполняет первую созданную goroutine. :) –

+1

как пользователи Go и goroutines, это все, что нам следует позаботиться –

+1

спасибо за ваш ответ. Это очень полезно для меня. –

Смежные вопросы