好吧,几年来,消费者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
首先将所有goroutines推入GRQ(全局运行队列)。每个逻辑CPU都具有其OS线程,其LRQ(本地运行队列)。 GO Scheduler从GRQ进行例程,然后将其随机放置在任何LRQ中。然后由相应的核心接收并执行。这确保并发和并行性。
如果您来自像我这样的分布式系统世界,那么感觉不像Go Scheduler就像Hadoop中的纱线调度程序吗?
特殊情况(不是那么特别的情况)
系统调用(例如I/O操作)是暂停程序执行直到完成所需操作的特殊情况。如果该例程停留在LRQ直到完成操作完成,则将浪费很多CPU周期,以便应用一个相当不错的解决方案。以单个LRQ。
的示例
说goroutine g7遇到了一个syscall。因此,它没有等待,而是发送到一个可以留在Syscall结束的地方。这是goroutines的停车位,
- 在频道上发送和接收
- 网络I/O
- 系统调用
- 计时器
- mutexes
准备执行后,G7再次发送到LRQ。