Goroutines的传说 - 并发和并发
#go #parallelism #goscheduler

parallelism and concurrency

好吧,几年来,消费者CPU的时钟速度一直持续到几个GHz。明显的解决方案是开始在彼此之间粘贴多个CPU核心,以提供更多的处理能力。这允许更多可用的计算周期。

如果您想运行许多非密集型CPU程序,这是一种很好的方法。 CPU调度程序像魅力一样工作,并在可用的CPU内核上分发单个任务。但是可以说,我们只有一份工作,希望在多个核心上分配它。这是程序和算法的设计。

GO是为多任务处理而设计的。多任务处理非常重要,以便在GO中​​启动并行过程,您只需要使用GO开始语句即可。看看下面的示例

func main(){
  for i := 1; i <= 3; i++{
    go func(n int){                // Parallel task is being created
      fmt.Printf("i : %d\n", n)
    }(i)
  } 
  time.Sleep(5 * time.Millisecond) // A sleep timer of 5 sec
}

Output:
i : 3
i : 1
i : 2

创建了三个并行任务,并且用户无法控制哪个将首先执行。每个平行任务称为 goroutine

如果您不添加睡眠计时器,您可能会获得任何输出,因为执行会等待Goroutine完成。但是,添加睡眠时间不是一个好主意,因为例行程序的执行是无法预测的。更好的方法是使用sync.Waitgroup

窗帘后面的goroutines

Go Scheduler in action

首先将所有goroutines推入GRQ(全局运行队列)。每个逻辑CPU都具有其OS线程,其LRQ(本地运行队列)。 GO Scheduler从GRQ进行例程,然后将其随机放置在任何LRQ中。然后由相应的核心接收并执行。这确保并发和并行性。

如果您来自像我这样的分布式系统世界,那么感觉不像Go Scheduler就像Hadoop中的纱线调度程序吗?

特殊情况(不是那么特别的情况)

系统调用(例如I/O操作)是暂停程序执行直到完成所需操作的特殊情况。如果该例程停留在LRQ直到完成操作完成,则将浪费很多CPU周期,以便应用一个相当不错的解决方案。以单个LRQ。

的示例

routine parking
说goroutine g7遇到了一个syscall。因此,它没有等待,而是发送到一个可以留在Syscall结束的地方。这是goroutines的停车位,

  • 在频道上发送和接收
  • 网络I/O
  • 系统调用
  • 计时器
  • mutexes

准备执行后,G7再次发送到LRQ。