转自敬维
转自C++爱好者博客
写在前面
常见的七种并发模型:线程与锁,函数式编程,Clojure,Actor,通信顺序进程(CSP),数据级并行,Lambda架构。
这篇博文把Actor和CSP两种模型简单介绍一下。
Actors模型
传统的并发模型主要由两种实现的形式:
- 一是同一个进程下,多个线程天然的共享内存,由程序对读写做同步控制(有锁或无锁).
- 二是多个进程通过
进程间通讯
或者内存映射
实现数据的同步.
Actors模型更多的使用消息机制来实现并发,目标是让开发者不再考虑线程这种东西,每个Actor最多同时只能进行一样工作,Actor内部可以有自己的变量和数据.
Actors模型避免了由操作系统进行任务调度的问题,在操作系统进程之上,多个Actor可能运行在同一个进程(或线程)中.这就节省了大量的Context切换.
Actor模型,顾名思义,侧重的是Actor。每个Actor与其他Actor进行直接通信,不经过中介,且消息时异步发送和处理的。
1
2
3Actor1 --> Actor2 --> Actor3
↓
Actor4这里隐含着这几种意思:
- 可以把每个过程(微进程,比如Elixir中的Process)当做一个Actor,能与其他的Actor互不干扰地并发运行。
- 如果Actor1想作用Actor2,必须通过发送消息的方式给Actor2发送”邮件“(地址直接填Actor2的地址),至于Actor2是否接受这份”邮件“,是Actor2的事情。
- 每个Actor有一个小邮箱,任意Actor可以向自己的地址发送的信息都会放置在这个邮箱里;信息的投递和读取是两个过程,这就把Actor之间的交互解耦了。
- 如果Actor1想给Actor4发送信息,必须要显式地把Actor4的地址(指针或者其他能找到Actor4的柄)给Actor1,否则Actor1是不知道把信息传到哪里去的。因此,如果用Actor模型编写代码,会有很多过程的Id要传递,顺理成章地也就有了父进程和子进程的说法。
CSP模型
CSP是 Communicating Sequential Processes(通信顺序进程) 的简称。
1
Worker1 --> Channel --> Worker2
在CSP中,多了一个角色Channel,过程(比如goroutine,Worker1)与过程(Worker2)之间不直接通信,而是通过Channle进行通信。
这里面也隐含着几种意思:
- Channel是过程的中间媒介,Worker1想要跟Worker2发信息时,直接把信息放到Channel里(在程序中其实就是一块内存),然后Worker2在方便的时候到Channel里获取。
- Worker1和Worker2之间可以存在很多个Channel;在Golang中每个Channel定义不同的数据类型,即发送不同类型的消息的时候会用到多个不同的Channel。
比较
- 和Actor模型比,CSP的Worker身上没有冗余的“信箱”;CSP模型把省下的内存空间都用来声明Channel了,所以不能说那种模型更节省内存。
- Actor模型假设Actor之间是经常有通信的,把“小邮箱”安装在每个Actor的身上,更适合用来进行高并发通信的场合,比如Erlang、Elixir。
- CSP模型,在解耦Worker之间通信的同时,提升了Worker的性能(没有小邮箱了,设计时不用考虑),比如Golang。
- 目前Golang(CSP模型)比Erlang以及Elixir(Actor模型)更火,后者比前者要小众一些。