专栏首页物流IT圈基于线程与基于事件的并发编程之争

基于线程与基于事件的并发编程之争

Java和Node.js可以说分别是基于线程和基于事件的两个并发编程代表,它们互相指责瞧不起对方,让我们看看各种阵营的声音: 基于事件的粉丝认为线程是一个坏主意,原因有是:

  • 你得显式的协调共享数据的锁,如果你忘记加锁,你就会得到中断坏的数据。
  • 依赖锁导致死锁。
  • 它们难以调试
  • 回调并没有锁
  • 多线程在多核上的性能并不会比每个单核一个线程性能更好。

你应当尽可能地避免线程,对于GUI和分布式系统或低端服务器不要用线程,只有处理CPU并发时才需要线程,如果必须使用线程,将线程隔离在核心内部,让大部分代码保持单线程。 而基于线程的粉丝认为Why events are a bad idea,反驳理由是:

  • 很多使用线程实现高并发却没有获得好性能?这其实假象,有人创建一个可扩展到100,000的线程库,其性能匹配SEDA的基于事件实现的性能。
  • 线程限制流程控制?线程派分析了基于事件的系统, 发现这些应用控制流程模式有三种:call-return, parallel calls和 pipeline. 这些都很容易使用线程表达。
  • 线程同步锁太重量?协调式多任务(协程)能让线程轻量等同于基于事件的并发。
  • 线程堆栈没有足够效率管理活动状态?不是,一个新的动态增长性堆栈stack模型可以解决这个问题。
  • 线程会阻止运行时刻进行优化调度决定?不是这样,Lauer 和-Needham 都显示不是这种情况。

线程派认为现代服务器虽然需要并发处理大量的请求,但是代码处理每个请求通常是有顺序的,我们相信线程提供这两种情况下很好的编程抽象。 尽管事件系统在高并发下有很好的性能,但是我们已经证明使用线程也会有类似性能(banq注:不过真的需要高手),由于语言提供编译时的分析使得线程简单,一样和基于事件系统能实现高并发。 线程派的改良代表可以首推Go的Goroutine和Python的coroutine协程,它们解决了直接基于OS线程导致线程上下文切换时带来的性能损耗,而且通过调度器保证非堵塞。Goroutine最大的特点能够让程序员以同步顺序代码的风格编写异步运行,Goroutine=coroutine协程 + user space threads + fibers + greenlets。因为绿色线程被封装在语言的API中,因此相比Node.JS显式处理异步IO,GO语言提供了隐式的异步处理IO,从而使得并发异步变得简单。 在GO语言的竞争之下,Node.JS一直探索如何避免回调陷阱,从Promise 到coroutine/Generators,直至演化到Javascript 7的async函数。从而也可以实现使用熟悉的顺序编程风格编写出异步代码,下面是使用JS 7的新的异步函数:

Javascript 7主要亮点是在事件机制和异步编程的提升上,这两点主要体现在: 1. Object.observe使得模型和视图之间很容易同步。 2. async函数更易于异步编程,能够实现拉Pull或推Push。

以Node.js为主的事件派和Go的协程派打得热乎时,这时有了一种观点,既然你们两者都回避各自缺陷表现得不错,下面是就剩下使用者的爱好和技能选择了,能不能提供一种语言将这两者结合在一起? Haskell倡导者提出通过语言统一多线程编程和事件编程,提供一种Monad函数,其内部封装了事件和多线程抽象,无论你是哪派粉丝,都可以使用这个Monad编程。

这种观点得到大多数人的同意,这时被冷落一边的Scala的Actor模型站出来认为自己的Actor函数属于这种两者合一的Monad函数。 当然,Go的绿色线程Goroutine与Actor还是有区别的。 纵观并发编程发展,大家都是从IO这个串行化端口入手,神仙过海,各显神招,从当初Java的NIO 到Node.JS的异步IO 再到Go的Goroutine以及Netty 以及Actor模型等等,应该说,谁在Socket IO这个战场上性能和易用性表现得更好,谁就可能在并发编程整个领域获得全胜。

本文分享自微信公众号 - 物流IT圈(exiter18)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-03-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 多线程让可扩展性走进了死胡同

    这是一篇来自Python世界的文章,但是对整个编程领域还是适用的,多线程虽然让我们处理请求更快,但是也是有天花板的,绿色(微线程micro-thread)线程之...

    物流IT圈
  • 异步编程:协作性多任务处理

    如何确保同时处理多个请求,我们可以使用线程或进程进行多任务处理实现,但还有一个选择 - 协作性多任务处理。 这个选项是最困难的。在这里我们说操作系统当然很酷...

    物流IT圈
  • JUC里的同步组件

    countDownLatch基于AQS的成员变量state实现的计数器,每次执行countDown()方法时,计数器减1,执行await()方法会阻塞线程直到计...

    物流IT圈
  • 谈Python多线程及程序锁

    Python中多线程使用到Threading模块。Threading模块中用到的主要的类是Thread,我们先来写一个简单的多线程代码:

    phith0n
  • 让人头大的各种锁,从这里让你思绪清晰

    说到了锁我们经常会联想到生活中的锁,在我们日常中我们经常会接触到锁。比如我们的手机锁,电脑锁,再比如我们生活中的门锁,这些都是锁。

    乱敲代码
  • Vista 及后续版本的新线程池

    在上一篇的博文中,说了下老版本的线程池,在Vista之后,微软重新设计了一套线程池机制,并引入一组新的线程池API,新版线程池相对于老版本的来说,它的可控性更高...

    Masimaro
  • 【你问我答】这些Java并发问题,专家是这么回答的

    针对上期Java高并发【你问我答】中读者提出的问题,王锐同学的回答如下。 一 ---- 美团内部使用过Akka么?有什么坑? ——Absurd “ 答: 只简...

    美团技术团队
  • 【40期】说一下线程池内部工作原理

    随着cpu核数越来越多,不可避免的利用多线程技术以充分利用其计算能力。所以,多线程技术是服务端开发人员必须掌握的技术。

    良月柒
  • 我画了25张图展示线程池工作原理和实现原理,原创干货,建议先收藏再阅读

    有朋友留言提到文中的场景是IO密集型操作,不是CPU密集操作,不需要使用线程池,我猜这位朋友可能想表达的是IO密集且阻塞时间久的不要使用线程池方案解决。IO密集...

    JavaQ
  • Java语言中的线程安全

    “ 在深入理解Java虚拟机一书的高效并发部分中提到:按照线程安全的安全程度由强至弱来排序,可以将Java语言中各种操作共享数据分为5类:不可变,绝对线程安全,...

    每天学Java

扫码关注云+社区

领取腾讯云代金券