The Scheduler Saga -- Golang

视频地址

传送门

视频说明

这个视频是说Golang的Goroutine的设计和调度,说得挺好

讲解的过程

视频里面循序渐进地讲述了Goroutine的Scheduler是如何设计的。

为什么需要协程
1.协程比系统线程要轻量级:不管是从创建销毁还是所占资源上面来说。
2.协程的调度比线程调度要快。
3.并发

Goroutine 和 系统线程如何协同工作
1.如何把Goroutine在线程之间分配。
2.在什么时候创建新的线程。

核心数据结构

核心数据结构 – runqueues
这个是一个分配在堆上面的队列,里面装的是待调度的Goroutine。

循序渐进的设计

第一版

把所有的Goroutine放在一个系统线程里面运行
问题:
1.如果一个Goroutine被阻塞,那么后面的Goroutine将不会得到运行的机会。
2.不能利用多核。

第二版

为每一个Goroutine创建一个线程。
问题:
这个跟直接创建一个线程再执行任务没什么区别。

第三版

复用线程:每当线程的数量小于Goroutine的数量时,创建一个新的线程,使用这个线程去运行Goroutine,但是运行完Goroutine之后,并不会把这个线程销毁,而是放入线程池。
问题:
线程会很多,并且对核心数据结构的加锁会影响效率,也会影响可扩展性。
线程会达到一个上限,不可能无止境地创建线程。

第四版

线程池:创建指定数量的线程,这个指定的数量为CPU的核数,这些线程都会操作同一个runqueue
问题
当CPU核心数多了之后,还是会出现锁的低效问题

第五版

为每一个线程分配一个runqueue,在哪一个线程里面创建Goroutine,那么就把Goroutine放入那个线程的runqueue
问题:
1.如何去平衡线程之间的Goroutine数量?
work stealing,如果当前线程的runqueue是空的,那么就去其他线程的runqueue里面去要几个过来。
2.当一个线程阻塞了,他创建的Goroutine怎么办?
如果有其他的线程处于空闲状态,那么其他线程会把这个Goroutine拿过去运行。如果其他线程都阻塞了,那么会创建一个新的线程来执行这个Goroutine,这个新的线程还是有一个runqueue
注意点
1.GOMAXPROCS:运行Goroutine的最大线程数量,所以如果很多的Goroutine阻塞[新任务会阻塞],那么还是会创建很多的线程出来。
2.会有一个monitor在后面监视这些线程的运行情况。
3.如果一个Goroutine占用了过多的CPU资源怎么办:在后台运行一个sysmon的线程,这个线程会去检测运行过久的Goroutine,并且把运行过久[>10ms]的Goroutine暂停掉,并且把暂停掉的Goroutine放到一个全局的runqueue里面。

当前调度器的缺陷

1.runqueue只是一个没有优先级的队列,所以会按照先进先出的顺序来运行Goroutine。
2.调度Goroutine时公平性没有很好的保证:已经提议进行修改。
3.runqueue没有利用缓存,使用缓存[栈而不是队列]可以加速Goroutine的访问。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值