goconcurrencychannelwaitgroup

Understanding Golang Concurrency: Unexpected Behavior with Buffered Channels


func taskScheduler(totalTasks int, taskQueue chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i:=0; i < totalTasks; i++ {
        fmt.Println("Scheduler is adding task to queue: ", i)
        taskQueue <- i
    }
    close(taskQueue)
}

func taskWorker(taskQueue chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for value := range taskQueue {
        fmt.Println("Working on task: ", value)
    }
}

func main() {
    var wg sync.WaitGroup
    taskQueue := make(chan int, 5)
    wg.Add(2)
    go taskScheduler(10, taskQueue, &wg)
    go taskWorker(taskQueue, &wg)
    wg.Wait()
}

Results from Console:
Scheduler is adding task to queue:  0
Scheduler is adding task to queue:  1
Scheduler is adding task to queue:  2
Scheduler is adding task to queue:  3
Scheduler is adding task to queue:  4
Scheduler is adding task to queue:  5
Scheduler is adding task to queue:  6
Working on task:  0
Working on task:  1
Working on task:  2
Working on task:  3
Working on task:  4
Working on task:  5
Working on task:  6
Scheduler is adding task to queue:  7
Scheduler is adding task to queue:  8
Scheduler is adding task to queue:  9
Working on task:  7
Working on task:  8
Working on task:  9

I expected to see two things that ultimately did not happen:

  1. The first round of the scheduler to have stopped at task 4 due to the buffer being full

  2. After stopping at task 4, the worker would work on task 0, then the scheduler would schedule task 5, and so on.

What is causing each goroutine to process 7 tasks at a time?
What is causing each goroutine to "take turns" performing their tasks. In other examples I see, once a channel is full, as data is being read from the channel, data is then added. Usually one at a time.

Thanks in advance!


Solution

  • This output suggests the following sequence of events:

    ...and so on