design patterns - Go - why do scheduling goroutine background workers also requires its own goroutine? -


i'm working on picking few of concurrency patterns of go. looked @ implementing background workers using goroutines , input/output channels, , noticed when sending new jobs receiving channel (essentially enqueuing new jobs) have in goroutine or scheduling gets messed up. meaning:

this crashes:

for _, jobdata := range(dataset) {     input <- jobdata } 

this works:

go func() {     _, jobdata := range(dataset) {         input <- jobdata     } }() 

for more concrete, played nonsense code (here in go playground):

package main  import (     "log"     "runtime" )  func dowork(data int) (result int) {     // ... 'heavy' computation     result = data * data     return }  // processing of input , return // results on output channel func worker(input, output chan int) {     data := range input {         output <- dowork(data)     } }  func scheduleworkers() {      input, output := make(chan int), make(chan int)      := 0 ; < runtime.numcpu() ; i++ {         go worker(input, output)     }      numjobs := 20      // doesn't work     // , crashes program     /*     := 0 ; < numjobs ; i++ {         input <-     }     */      //     go func() {         := 0 ; < numjobs ; i++ {             input <-         }     }()      results := []int{}     := 0 ; < numjobs ; i++ {         // read off results         result := <-output         results = append(results, result)         // stuff...     }      log.printf("result: %#v\n", results) }  func main() {     scheduleworkers() } 

i'm trying wrap head around subtle difference - appreciated. thanks.

your scheduleworks function sends, in main goroutine (ie. 1 runs main() function, in program starts), value via input. worker receives it, , sends value via output. there nobody receiving output @ point, program can't go on, , main goroutine sends next value worker.

repeat reasoning each worker. have runtime.numcpu() workers, less numjobs. let's runtime.numcpu() == 4, have 4 workers. @ end, have sent 4 values, each 1 one worker. since nobody reading output, workers busy trying send, can't accept more data via input, fifth input <- i hang. @ point every goroutine waiting; that's deadlock.

enter image description here

you notice that, if launch 20 or more workers instead of runtime.numcpu(), program works. that's because main goroutine can send wants via input, since there enough workers receive them.

if, instead of of this, put input <- i loop in goroutine, in successful example, main goroutine (in scheduleworks runs) can go on , start reading output. so, each time new goroutine sends value, worker sends via output, main goroutine gets output, , worker can receive value. nobody waits, , program succeeds.

enter image description here


Comments

Popular posts from this blog

android - Get AccessToken using signpost OAuth without opening a browser (Two legged Oauth) -

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: mockito -

google shop client API returns 400 bad request error while adding an item -