2015-05-21 2 views
2
  • Редактировать * - раскорить две строки времени выполнения и изменить Tick() на Sleep(), и он работает как ожидается, печатает один номер каждую секунду. Оставляя код, так это ответ и комментарии имеют смысл.

идти версия go1.4.2 Darwin/amd64Основная нить не доходит до goroutine

Когда я запускаю следующее, я никогда не видел ничего напечатал от go Counter().

package main 

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

var count int64 = 0 

func main() { 
    //runtime.GOMAXPROCS(2) 
    fmt.Println("main") 
    go Counter() 
    fmt.Println("after Counter()") 
    for { 
    count++ 
    } 
} 

func Counter() { 
    fmt.Println("In Counter()") 
    for { 
    fmt.Println(count) 
    time.Tick(time.Second) 
    } 
} 

> go run a.go 
main 
after Counter() 

Если я раскомментировать выполнения вещи, я буду получать некоторые странные результаты, как следующие все печатные сразу (а не второй друг от друга):

> go run a.go 
main 
after Counter() 
In Counter() 
10062 
36380 
37351 
38036 
38643 
39285 
39859 
40395 
40904 
43114 

Что я ожидаю, что go Counter() будет печатать все count происходит каждую секунду, пока он непрерывно увеличивается по основному потоку. Я не столько ищу другого кода, чтобы сделать то же самое. Мой вопрос больше о том, что происходит, и где я ошибаюсь в своих ожиданиях? Вторые результаты, в частности, не имеют никакого смысла, печатаются все сразу. Насколько мне известно, они никогда не должны печататься ближе, чем я могу сказать, не так ли?

+2

Я думаю, что вы ошибаетесь 'время.Tick' для' time.Sleep'. – tomasz

+1

Выключает это изменение, поэтому он работает так, как ожидалось (с GOMAXPROCS = 2). – LanceH

+0

Yup, все тайны решены менее чем за 10 минут. Viva SO! – tomasz

ответ

6

В вашей жесткой петле for ничего не происходит, что позволяет запустить планировщик Go. Расписание рассматривает другие goroutines всякий раз, когда вы блокируете или на некоторых (которые? Все?) Вызовы функций.

Поскольку вы не сделаете ни одно из самых простых решений, это добавить звонок в runtime.Gosched. Например .:

for { 
    count++ 
    if count % someNum == 0 { 
     runtime.Gosched() 
    } 
} 

отметить также, что запись и чтение ту же переменную из разных goroutines без блокировки или синхронизации гонки данных и there are no benign data races, ваша программа могла бы сделать что-нибудь при чтении значения, как это пишется. (И синхронизация также позволит запустить планировщик Go.)

Для простого счетчика вы можете избежать блокировок с помощью atomic.AddInt64(&var, 1) и atomic.LoadInt64(&var).

Обратите внимание, что time.Tick ничего не задерживает, возможно, вам потребовалось time.Sleep или for range time.Tick(…).

+0

Отличный ответ (не может принять его еще на 6 минут). – LanceH

+1

Переключение на time.Sleep() с GOMAXPROCS = 2 и работает так, как ожидалось. Я знаю, что этот бит кода был беспорядок с гонкой данных в нем, но я пытался устранить проблему из чего-то большего, чтобы задать вопрос, который вы ответили. Спасибо. – LanceH