golang goroutine

使用

  • goroutine无法设置优先级,无法获取ID,没有局部储存,返回值被忽略
    • 可以通过channel传递返回值
  • 通过设置runtime.GOMAXPROCS(n)可以控制真正的并行度
    • 默认值为CPU核数:runtime.GOMAXPROCS(runtime.NumCPU())
      • 在某些IO密集型的应用里,这个值可能并不意味着性能最好
        • 理论上当某个Goroutine进入系统调用时,会有一个新的M被启用或创建,继续占满CPU。但由于Go调度器检测到M被阻塞是有一定延迟的,也即旧的M被阻塞和新的M得到运行之间是有一定间隔的
        • 所以在IO密集型应用中不妨把GOMAXPROCS设置的大一些
    • 并不一定是物理线程数
      • 如果物理线程阻塞在系统调用,会开启更多的物理线程(M)
        • 陷入系统调用被阻塞时M将释放P给某个空闲的M,继续执行P队列中剩下的G
      • 只有 n 个活跃的线程执行 user-level 代码

-

  • 可以利用runtime.Gosched()让协程轮流执行

    • runtime.Gosched()表示让CPU把时间片让给别人,下次某个时候继续恢复执行该goroutine
    • 该函数很少被使用,因为无法保证调度总是成功
  • defer一样, goroutine也会对传入的参数立刻进行计算

var c int
func counter() {
    c++
    return c
}   

go func(x){
    counter()
    fmt.Print(x) // 打印出0,而不是1
}(counter())
  • 并行for循环
    • 注意i, xi需要通过参数传入而不能当成闭包的环境,否则会出错
      • 也可以在for循环中赋值给新建的局部变量解决
    • 原因在于i, xi在循环的过程中地址不变
for i, xi := range data {
	go func (i int, xi float64) {
		res[i] = doSomething(i, xi)
		sem <- empty
	} (i, xi)
}
// wait for goroutines to finish
for i := 0; i < N; i++ { <-sem }
  • 多个goroutine协调工作涉及 通信,同步,通知,退出 四个方面
    • 通信:chan通道是各goroutine之间通信的基础。注意这里的通信主要指程序的数据通道。
    • 同步:可以使用不带缓冲的chan;sync.WaitGroup为多个gorouting提供同步等待机制;mutex锁与读写锁机制。
    • 通知:通知与上文通信的区别是,通知的作用为管理,控制流数据。一般的解决方法是在输入端绑定两个chan,通过select收敛处理。这个方案可以解决简单的问题,但不是一个通用的解决方案。
    • 退出:简单的解决方案与通知类似,即增加一个单独的通道,借助chan和select的广播机制(close chan to broadcast)实现退出

原理

  • goroutine采用M:N模型,在所有线程上进行多路复用

    • 当一个goroutine被阻塞时,所在的线程也被阻塞,而go的runtime会把该线程上的其他协程移动到未阻塞的线程
      • 已存在的 goroutine 总是会被优先复用
    • 每个goroutine拥有自己的寄存器上下文和栈
    • 优点
      • 控制了系统线程的数量
        • 保证每个线程一定的运行时间
        • 避免线程过多而导致调度开销过大
      • 程序可以在用户态自行调度
        • 避免了单个协程阻塞了整个线程的情况、
        • 避免了大量内核态和用户态切换
      • 更小的栈空间占用
        • 允许用户创建成千上万的实例
  • 调度方式

    • 在runtime中实现了一个调度器, 一旦进行了Golang库函数调用, runtime就有机会进行调度
      • 如果写了死循环就没法触发goroutine的调度
    • 操作系统会在物理处理器上调度线程来运行,而Go 语言的运行时会在逻辑处理器上调度
      goroutine来运行
    • 调度器把goroutine调度到的CPU不一定是程序进程所在的CPU

在这里插入图片描述

  • 只要P不空闲,就可以保证充分利用CPU
  • 一般情况下M的个数会略大于P的个数
    • 这多出来的M将会在G产生系统调用时发挥作用
      在这里插入图片描述在这里插入图片描述
      在这里插入图片描述

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值