说说协程coroutine

作者: NickYang 分类: 心情随笔 发布时间: 2017-05-07 14:06

近几年来,协程的概念和使用被越多越多的人提到了,确实帮助很多人解决了很多问题,例如网络上的问题,异步逻辑流程控制等。我的工作中也接触到一些,所以打算总结下。

简单来说,协程就是一种用户态、编程语言层面的轻量级线程。

然而线程与协程又有很多差异的地方,线程是靠操作系统OS本身来调度,是抢占式的任务处理方式,谁抢到算谁的,所以大部分多线程程序中都要单独调用sleep来让出CPU给其他线程;线程每次阻塞、切换时都需要系统调用system call,然后调用调度函数来决定运行哪一个线程;协程拥有自己的用户态的上下文和栈(分为stackless和stackfulness,这个下一篇文章来讲),协程切换时,先将寄存器上下文和栈内容保存起来,再次切换回来的时候再恢复之前保存的内容继续运行;

通过上面的讲解,明白了一个道理,协程是编译器来保证的,线程是操作系统来调度的;协程能更好的保证流程,而线程需要仔细处理公共数据资源;协程本质是单线程的,能提高单个CPU core的性能,适合计算密集型的应用;协程切换非常轻量,所以能大量的使用,线程切换成本较高,一般要控制线程数。

 

协程的概念和原理明白了后,其实有点类似于异步事件驱动,可以看看libevent/libuv等经典的C语言库,发现大量使用了异步事件回调,有一个event_loop来循环检查要处理的事件,不过就是代码相对协程恶心了一些,协程能让用户以类似同步的方式来处理异步流程,更加便于理解。

 

不过协程也是有缺点的,无法利用现代多核机器的性能,所以还需要配合多进程来提高性能;有阻塞操作的时候依然会阻塞整个进程,需要用其他方式来解决。

还有一个东西是actor,这个是更符合人类思维的方式,属于类似消息通知的方式来处理异步事件,可惜现在没有非常好用的actor cpp库,其他语言有类似的库,例如Java的akka, .net的Akka.net, Orleans/Service fabric等。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

3条评论
  • rangerlee

    2017 年 8 月 10 日 22:09

    C++里面其实在boost里面已经有了协程,asio特别配合实现了协程版本的IO,个人版本的协程非常多。比较有意思的是以前有statethread,现在有libgo,这些库的优势就是进行了syscall的hook(当然也很easy),意思就是所有socket阻塞函数被hook改成了异步以实现协程,而且程序依赖的第三方库如mysqlclient,redis等都不需要进行修改,程序要做的就是写业务逻辑。我尝试用libgo做了web服务外加redis操作,性能还是不错的,也能同时跑在多核心上,因为使用协程,完全可以当作单线程程序来写业务逻辑,有时间打算写个web代理,理论上还是非常简单的。另外当前的协程都是各种奇技淫巧,期待标准库整进去。

    畅言 Chrome浏览器 Windows 10 x64 Edition
    1. NickYang

      2017 年 8 月 14 日 09:50

      libgo是挺好用的,我也考虑引入使用了。不过我们这边项目都是自己造的轮子。而且特别还是C的,只能支持linux,不能跨平台

      站长 QQ浏览器 Windows 7 x64 Edition
  • vfhky

    2017 年 6 月 22 日 09:41

    go python这些弄进来的概念,apue上只有进程和线程的概念。

    潜水 Chrome浏览器 Windows 10 x64 Edition

发表评论

电子邮件地址不会被公开。 必填项已用*标注