谈谈并发编程中的协程

高并发编程里多线程(进程)的弊端
其实从著名的 C10K 问题的时候, 就谈到了高并发编程时, 采用多线程(或进程)是一种不可取的解决方案, 核心原因是因为线程(或进程)本质上都是操作系统的资源, 每个线程需要额外占用1M或者2M的内存空间, 所以2G内存,能承受的线程数差不多只能到1k这个量级。
而且线程的调度由操作系统调度, 当线程或者进程数到达一定量级的时候, 据有人试验的结果是并发的线程数到达1k以上后, 操作系统基本上就已经不堪重负,调度不过来了。
事件驱动
已知多线程已经无法解决高并发问题, 所以才有了异步IO,事件驱动等概念来解决高并发编程。 很典型的就是 Node.js ,传说中的事件驱动, 其实就是在底层使用了 libuv 然后通过各种回调函数来注册事件, 当事件触发的时候回调函数也被触发。 使用事件驱动的方式确实能解决高并发的问题, 但是因为事件驱动最费劲的就是各种丧心病狂不停的回调, 在回调里面再嵌套回调,容易陷入所谓的【回调地狱】。 这也是 Node.js 最受人诟病的地方。
高并发解决方案之协程
面向对象最典型的语言是 Java , 事件驱动最典型的语言是 Node.js , 协程最典型的语言就是 golang , 当然国内程序员响马的 fibjs 也是基于协程来进行并发的, 也非常出色,只不过在生态上还是发展的太慢了。 个人看来协程相对于事件驱动是一种更先进的高并发解决方案, 把复杂的逻辑和异步都封装在底层, 让程序员在编程时感觉不到异步的存在, 用响马的话就是【用同步抒写异步情怀】。 个人很看好协程的发展, 同时也非常看好 golang 的前景,

协程也叫用户级线程, 很多人分不清楚协程和线程和进程的关系。 简单的说就是: 线程和进程的调度是由操作系统来调控, 而协程的调度由用户自己调控。 所以协程调度器可以在协程A即将进入阻塞IO操作, 比如 socket 的 read (其实已经设置为异步IO )之前, 将该协程挂起,把当前的栈信息 StackA 保存下来, 然后切换到协程B, 等到协程A的该 IO操作返回时, 再根据 StackA 切回到之前的协程A当时的状态。

小结

协程诞生解决的是低速IO和高速的CPU的协调问题,解决这类问题主要有三个有效途径:

1.异步非阻塞网络编程(libevent、libev、redis、Nginx、memcached这类)

2.协程(golang、gevent)

3.“轻量级线程”,相当于是在语言层面做抽象(Erlang)

对比之下协程的编程难度较低,不要求编程人员要有那么高的抽象思维能力。再加上golang在这方面优秀的实践,协程目前的前途还是一片光明的。当然还有一点,我们要承认无论你状态机、callback设计得多么精妙,现实中阻塞事很难以避免的。

  • 避免了Network IO Blocking,
  • 还有数据库Blocking,
  • 还有Disk IO Blocking,
  • 还有数据库Blocking,
  • 还有日志Blocking,
  • 还有第三方库blocking,
  • 还有人类自己导致的blocking……
协程是应对这些的不错的解决方案,当然协程的接口还是太过晦涩。So,Life is Short,Use Golang。线程还是更适合作为多核计算的不二法门存在的。

原文链接:https://studygolang.com/articles/2396

你可能感兴趣的:(谈谈并发编程中的协程)