用了这么多年java,觉得java不支持协程就是无脑的行为,必须为go支持协程点个赞,最近在优化性能,对过了这么多年java仍然没在语言级提供协程感觉痛心,刚好看到一篇文章: https://www.jianshu.com/p/837bb161793a C++ 协程的近况、设计与实现中的细节和决策,做个总结
1、需要协程的理由:
线程切换也非常重量级,不能无限增加线程,操作系统调度不过来
2、实现协程需要哪些特性:
a)支持协程上下文切换,实现方案可以基于操作系统、汇编语言、或者第三方封装(比如boost),难度不一,兼容性和效率也不一
b)协程占管理,如果和线程一样的重,那么也没有协程的必要了
静态栈(Static Stack):固定大小,典型的:libco
分段栈(Segmented Stack):gcc提供的“黄金链接器”支持一种允许栈内存不连续的编译参数,实现原理是在每个函数调用开头都插入一段栈内存检测的代码,如果栈内存不够用了就申请一块新的内存,作为栈内存的延续
拷贝栈(Copy Stack):每次检测到栈内存不够用时,申请一块更大的新内存,将现有的栈内存copy过去,就像std::vector那样扩展内存。
虚拟内存栈(Virtual Memory Stack):利用操作系统的虚拟内存,libgo为每个协程malloc 1MB的虚拟内存作为协程栈(这个值是可以定制化的);不做读写操作就不会占用物理内存,协程栈使用了多少才会占用多少物理内存,实现了与共享栈近似的内存使用率,并且不存在共享栈的两大弊端。
c)协程调度:可以参考操作系统各种传统的调度方式和延伸
d)HOOK接口:在协程中调用接口是否和在线程中调用一样,这个主要针对网络IO和协程中的数据交换。基本守则:HOOK接口表现出来的行为与被HOOK的接口保持100%一致基本守则:HOOK接口表现出来的行为与被HOOK的接口保持100%一致
3、现有协程库的选择
如果可能,选择go
c++的libgo据说不错,知乎上评价:https://www.zhihu.com/question/51817323,官方地址:https://github.com/yyzybb537/libgo
最后,真心的觉得java和c++提供一个语言层面的协程库吧,都好几十年了,还这德行。
如果做高并发的话,推荐鸟窝的博客: https://colobu.com/ ,在应用go方面还是有不少的经验可取