协程优势及其通信方式
协程优势及其通信方式
协程相当于是用户态的线程
进程切换消耗资源很大,且进程间通信较复杂,于是有了线程
每个线程都有自己的堆栈和寄存器,并共享所属进程内的其他资源,因此可以方便地实现线程切换和通信,但是也由于多个线程共享地址空间,任何一个线程出错时,同进程内的所有进程都会崩溃
但是线程也难以实现高并发,因为:
- 线程消耗的内存还是很多,在linux系统中高达8MB,同时为了解决线程申请堆内存时互相竞争的问题,每个
线程预先在这个空间内预分配了64MB作为堆内存池,因此没有足够的内存去开启十几万的线程实现并发
- 线程切换耗时:线程的切换是由内核控制的,因此当线程繁多的时候,线程间的切换会消耗cpu很多的计算能
力
而协程使本来由内核实现的切换工作,交给了用户态的代码完成
通常创建协程时,会从进程的堆上分配一段内存作为协程的栈,线程的栈有8M,而协程的栈只有几十K
每个协程都有独立的栈,在go语言中,运行时系统会帮助自动创建和销毁系统线程,而对应的用户级协程是架设在线程之上的,用户级协程的创建销毁和调度都完全由程序实现和处理,而不用经过操作系统去做,速度会很快,很
容易控制和灵活
因此总结下来,协程的优势有:
- 节省cpu,避免系统内核级的线程频繁切换造成的cpu资源浪费
- 节约内存
- 稳定性
- 开发效率,协程是合作式的,可以方便地将一些操作异步化
Go中协程的通信方式
可以通过共享内存(变量)加锁的方式来进行通信,但是维护成本较高
官方推荐通过channel进行通信:
channel的主要功能是:
- 作为队列存储数据
- 阻塞和唤醒goroutine
select:
select搭配channel使用,其机制是监听多个channel,每一个case都是一个事件,一旦某个事件就绪(chan没有堵塞),就会从这些就绪事件中随机选择一个去执行,default用于所有chan都堵塞的情况执行
使用channel进行控制子goroutine的机制可以总结为:
循环监听一个channel,在循环中可以放select来监听channel达到通知子goroutine的效果,再配合Waitgroup,主进程可以等待所有协程结束后再自己退出;这样就通过channel实现了优雅控制goroutine并发的开始和结束
全站分卷索引 · 29 卷
- 1代码随想录知识星球精华(最强八股文)第五版(Go篇))
- 2Go string 和 []byte 的区别
- 3数组和切片的区别
- 4扩容前后的Slice是一样的吗
- 5Go语言map是有序的还是无序的, 为什么
- 6go里面的map是并发安全的吗?如何并发安全
- 7Go 的错误处理和 Java 的异常处理对比
- 8介绍一下panic和recover
- 9什么是defer?有什么作用
- 10Go并发
- 11进程、线程的区别
- 12什么是go runtine
- 13Go语言中的Channel是什么, 有哪些用途,如何处理阻塞
- 14什么是互斥锁(mutex)?在什么情况下会用到它们?
- 15Mutex有几种模式
- 16goroutine什么情况会发生内存泄漏?如何避免。
- 17Go语言中GC的流程是什么
- 18Go 中的内存逃逸现象是什么?
- 19CAP 理论,为什么不能同时满足
- 20说一下 Gin 的路由怎么实现的
- 21简述slice的底层原理,和数组的区别是什么
- 22defer底层原理
- 23侵入式和非侵入式的区别
- 24goroutine与线程的区别
- 25goroutine在什么情况下会被挂起呢?
- 26GC(垃圾回收)原理 1.5版本
- 27简述Go的垃圾回收机制
- 28协程优势及其通信方式
- 29Go的内存对齐