2015-02-24 3 views
3
package main 

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

func main() { 
    intInputChan := make(chan int, 50) 
    var wg sync.WaitGroup 
    for i := 0; i < 3; i++ { 
     wg.Add(1) 
     go worker(intInputChan, wg) 
    } 
    for i := 1; i < 51; i++ { 
     fmt.Printf("Inputs. %d \n", i) 
     intInputChan <- i 
    } 
    close(intInputChan) 
    wg.Wait() 
    fmt.Println("Existing Main App... ") 
    panic("---------------") 
} 

func worker(input chan int, wg sync.WaitGroup) { 
    defer func() { 
     fmt.Println("Executing defer..") 
     wg.Done() 
    }() 

    for { 
     select { 
     case intVal, ok := <-input: 
      time.Sleep(100 * time.Millisecond) 
      if !ok { 
       input = nil 
       return 
      } 
      fmt.Printf("%d %v\n", intVal, ok) 

     default: 
      runtime.Gosched() 
     } 
    } 

} 

ошибка брошена есть.Почему все горуты спит - тупик. Идентификация узкого места

Неустранимая ошибка: все горуты спит - тупик!

goroutine 1 [semacquire]: синхронизации (* WaitGroup) .Wait (0xc082004600) C:. /go/src/sync/waitgroup.go: 132 + 0x170 main.main() Е:/Перейти /go_projects/go/src/Test.go:22 + 0x21a

+1

Вместо того, чтобы писать 'вар sync.WaitGroup' написать РГ' РГ: = новый (sync.WaitGroup) ', и вы никогда не будете повторите эту ошибку! –

+0

-1: [Некоторые вопросы по-прежнему не соответствуют теме, даже если они вписываются в одну из категорий, перечисленных выше: Вопросы, требующие помощи по отладке («почему этот код не работает?») Должны включать в себя желаемое поведение, конкретную проблему или ошибки и кратчайший код, необходимый для воспроизведения в самом вопросе. Вопросы без четкой постановки проблемы не полезны другим читателям] (http://stackoverflow.com/help/on-topic) – Vector

ответ

8

Я только что попробовал (playground), пропустив wg *sync.WaitGroup, и он работает.

Передача sync.WaitGroup означает передачу копию sync.WaitGroup (проходящий по значению): при регистрации goroutine упоминает Done() к различногоsync.WaitGroup.

var wg sync.WaitGroup 
for i := 0; i < 3; i++ { 
    wg.Add(1) 
    go worker(intInputChan, &wg) 
} 

Обратите внимание на &wg: вы передаете по значению указателя к исходному sync.WaitGroup, для goroutine использовать.

3

Как уже упоминался, не проходят типов из синхронизации пакета вокруг по значению, в непосредственной близости от верхней части sync package documentation: «Значение, содержащее типов, определенных в этом пакете не должно быть скопировано.» Это также включает в себя тип самостоятельно (sync.Mutex, sync.WaitGroup, и т.п.).

Однако некоторые примечания:

  • Вы можете использовать только один вызов wg.Add, если вы знаете, сколько вы собираетесь добавить (но, как документально убедиться, что это сделано , прежде чем нибудь может назвать Wait).
  • Вы не хотите звонить runtime.Gosched; это заставляет рабочих заняться циклом.
  • Вы можете использовать range для чтения с канала, чтобы упростить остановку, когда он закрыт.
  • Для небольших функций вы можете использовать закрытие и не беспокоиться о том, чтобы передать канал или группу ожидания вообще.

Это превращает его в это:

package main 

import (
    "fmt" 
    "sync" 
    "time" 
) 

func main() { 
    const numWorkers = 3 

    c := make(chan int, 10) 
    var wg sync.WaitGroup 

    wg.Add(numWorkers) 
    for i := 0; i < numWorkers; i++ { 
     go func() { 
      defer func() { 
       fmt.Println("Executing defer…") 
       wg.Done() 
      }() 

      for v := range c { 
       fmt.Println("recv:", v) 
       time.Sleep(100 * time.Millisecond) 
      } 
     }() 
    } 

    for i := 1; i < 51; i++ { 
     fmt.Println("send:", i) 
     c <- i 
    } 
    fmt.Println("closing…") 
    close(c) 

    fmt.Println("waiting…") 
    wg.Wait() 
    fmt.Println("Exiting Main App... ") 
} 

playground

+0

Спасибо, что VonC & Dave изменил его на ссылочный тип. – VimleshS

+0

Мне понравились все заметки, которые вы упомянули. Можете ли вы, пожалуйста, добавить еще одну теорию для точки nos 3 (диапазон для чтения с канала) или указатель также может помочь. – VimleshS

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