思索了这两个问题良久,也去知乎找了一些相关话题的问答,但并没有标准答案。所以,我这里也只是记录一些我对此的看法,也许会随着 RTFSC 阅历的丰富而发生变化,我会记录更新于 。
并行编程,异步编程,响应式编程,TPL数据流,多线程,Actor模型
微软还特意把异步编程分作了3种不同的模型
基于任务的模式(TAP),基于事件的模式(EAP)和异步编程模型(APM)
1. 并行编程
把正在执行的大量任务分成多块,分给不同线程处理同时处理。
并行编程的思想实在多核cpu的基础上兴起的,为了让cpu的利用率最大化。
比如你的cpu是4核,当前一个现在在1个核上运行,其它3核处于空闲状态,这个肯定是不合理的。
所以并行编程,是将多个同时运行的线程放到不同的核上。并行编程是多线程的一种,多线程是并发的一种。
.net 4.0 引入的任务并行库和并行LINQ
2.异步编程
采用future模式(又称promise)模式或回调机制(Non-blocking on waiting),关于future模式这里就不具体介绍了。
在老的api中,采用的是时间(event)回调,而不是feture。现在.Net中feture类型有Task,Task
使用异步编程有两个好处,1.不阻塞原来的线程,2.增加服务器的吞吐量
3.响应式编程
框架有Rx、Bacon.js、RAC。
简单来说响应式编程就是讲事件流看作数据流,只是数据流逝从IEnumable中拉取,而事件流是从IObservable推送给你的。起初理解响应式编程比较难,但是一旦理解就简单了。
为什么响应式编程能处理并发呢?拿Rx举例,Rx做到线程不可知,当每次触发事件,都会从线程池中获取一个线程来进行处理。且可以对事件设置窗口期和限流。
最后,响应式编程不一定是并发的,但是它和并发是密不可分的。
4. TPL数据流编程
数据流(DataFlow)编程可能大家就更陌生了,不过还是有些常用场景可以使用数据流来解决。数据流其实是在任务并行库(TPL)上衍生出来的一套处理数据的扩展(也结合了异步的特性),TPL也是处理并行编程中任务并行和数据并行的基础库。
TPL DataFlow就是对数据进行一连串处理,首先为这样的处理定义一套网格(mesh),网格中可以定义分叉(fork)、连接(join)、循环(loop)。数据流入这样的处理网格就能够并行的被处理。你可以认为网格是一种升级版的管道,实际上很多时候就是被当作管道来使用。使用场景可以是“分析文本文件中词频”,也可以是“处理生产者/消费者问题”。
5. 多线程
这个就不用多介绍了
6. Actor模型
特别的关注锁和内存原子性等一系列线程问题,而Actor模型内部的状态由它自己维护即它内部数据只能由它自己修改(通过消息传递来进行状态修改),所以使用Actors模型进行并发编程可以很好地避免这些问题。 Actor由状态(state)、行为(Behavior)和邮箱(mailBox)三部分组成
1.状态(state):Actor中的状态指的是Actor对象的变量信息,状态由Actor自己管理,避免了并发环境下的锁和内存原子性等问题
2.行为(Behavior):行为指定的是Actor中计算逻辑,通过Actor接收到消息来改变Actor的状态
3.邮箱(mailBox):邮箱是Actor和Actor之间的通信桥梁,邮箱内部通过FIFO消息队列来存储发送方Actor消息,接受方Actor从邮箱队列中获取消息
使用Actor模型好处
1.事件模型驱动–Actor之间的通信是异步的,即使Actor在发送消息后也无需阻塞或者等待就能够处理其他事情
2.强隔离性–Actor中的方法不能由外部直接调用,所有的一切都通过消息传递进行的,从而避免了Actor之间的数据共享,想要观察到另一个Actor的状态变化只能通过消息传递进行询问
3.位置透明–无论Actor地址是在本地还是在远程机上对于代码来说都是一样的
4.轻量性–Actor是非常轻量的计算单机,单个Actor仅占400多字节,只需少量内存就能达到高并发