了解 Golang 并发:缓冲通道的意外行为

问题描述 投票:0回答:1
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

我期望看到两件事最终没有发生:

  1. 由于缓冲区已满,第一轮调度程序在任务 4 处停止

  2. 在任务 4 处停止后,工作人员将处理任务 0,然后调度程序将调度任务 5,依此类推。

是什么导致每个 goroutine 一次处理 7 个任务?
是什么导致每个 goroutine “轮流”执行其任务。在我看到的其他示例中,一旦通道已满,当从通道读取数据时,就会添加数据。通常一次一个。

提前致谢!

go concurrency channel waitgroup
1个回答
0
投票

此输出表明以下事件顺序:

  • taskScheduler
    循环0-4,发送任务到通道
  • 发生这种情况时,
    taskWorker
    收到其中一项任务
  • taskWorker
    可以打印之前,
    taskScheduler
    又发送了一个任务(5),然后打印出正在调度 6,并阻塞。
  • taskWorker
    从通道读取,并打印0-5
  • 由于通道不可写,任务调度程序发送 6
  • taskWorker
    打印 6

...等等

© www.soinside.com 2019 - 2024. All rights reserved.