<blockquote>An object oriented language is a language with good support for objects.
A concurrency oriented language has good support for concurrency.
--Joe Armstrong</blockquote>
两类通用并发模型:参考七周七并发模型
共享内存型Shared Memory
- 线程Threads
- 锁Locks
- 互斥l量Mutexes
音讯传送型(CSP和Actor模型)
- 过程Processes
- 音讯Messages
- 不共享数据(状态)No shared data
重点介绍音讯传送型的两种模型Actor和CSP(Communicating Sequential Process)的各项比照
次要目标:除了罕用的Python、Java等用的并发模型之外,还存在这么个货色
<!--more-->
先看两段代码
代码示例比照
应用Erlang代码和Go代码别离实现打印服务print_server,用来比照模型应用差别
Actor模型-Erlang代码
%%%-------------------------------------------------------------------%%% @author Suncle%%% @doc%%% print_server%%% @end%%% Created : 2017/12/18 14:53%%%--------------------------------------------------------------------module(print_server).-author("Flowsnow").%% API-export([print_server/0, start_print_server/0, send_msg/2]).print_server() -> receive Msg -> io:format("print_server received msg: ~p~n", [Msg]), print_server() end.start_print_server() -> Pid = spawn(?MODULE, print_server, []), Pid.send_msg(Msg, Pid) -> Pid ! Msg, io:format("send_normal_msg: ~p~n", [Msg]).
Erlang shell输入后果如下:
1> c("print_server.erl").{ok,print_server}2> Pid = print_server:start_print_server().<0.39.0>3> print_server:send_msg("hello", Pid).send_normal_msg: "hello"print_server received msg: "hello"ok
以上print_server应用的是最原始的Erlang语法实现的,也能够应用OTP gen_server原语实现更加清晰易懂
CSP模型-Go代码
print函数从channel读取音讯并阻塞,直到主函数向channel写入hello音讯
package mainimport ( "fmt" "time")func main() { c := make(chan string) go print(c) time.Sleep(1 * time.Second) fmt.Println("main function: start writing msg") c <- "hello" var input string fmt.Scanln(&input)}func print(c <-chan string) { fmt.Println("print function: start reading") fmt.Println("print function: reading: " + <-c) time.Sleep(1 * time.Second)}
输入后果如下:
D:\workspace\Go>go run print_server.goprint function: start readingmain function: start writing msgprint function: reading: hello
模型图比照
Actor
Actor1发送音讯到Actor2的邮箱中,邮箱实质是队列,由Actor2生产
CSP
Process1在Channel的写入端增加音讯,Process2在channel的读取端读取音讯
根本个性比照
Actor
- 基于消息传递message-passing
- 音讯和信箱机制:音讯异步发送
- 保留可变状态但不共享
- 失败检测和任其解体
- 重点在于发送音讯时的实体
CSP
- 基于消息传递message-passing
- 顺序进程Sequential processes
- 通过channel同步通信Synchronous communication through channels
- 频道交替复用Multiplexing of channels with alternation
- 重点在于发送音讯时应用的通道channel
通信语义比照
Actor
Actor1期待音讯并阻塞,直到Actor2发送音讯给Actor1Actor2发送音讯给Actor3,暂存在Actor3的Mailbox中,直到Actor3承受并解决
CSP
Process1读取channel因没有音讯阻塞,直到Process2向该channel增加音讯process2向channel增加音讯并阻塞,直到Process3读取该channel音讯
Erlang实现繁难银行账户
应用Erlang原语,代码如下:
- https://gist.github.com/Flows...
应用OTP的gen_server,代码如下:
- https://gist.github.com/Flows...
Erlang小我的项目:IP数据库
应用Erlang/OTP实现的IP数据库,能够依据IP查问到具体的国家省份等,代码如下:
- https://github.com/Flowsnow/i...
不一样的Erlang个性
- Let it crash思维:值得借鉴
- https://www.zhihu.com/questio...
比方:执行算术异样解体
- 变量是不可变的,变量一旦赋予值就无奈再扭转:带来的益处就是没有可变状态,就不须要内存共享,也就不须要有锁
- Erlang过程之间的惟一交互方式就是消息传递:Erlang中没有像C++那样,过程间领有多种不同的交互方式(管道、音讯队列、存储共享等等)。
FAQ
为什么没有容量主动增大的缓冲区?
即便当初有一个看上去永不枯竭的资源,总有一天这个资源还是会被用尽的。可能是因为时过境迁,当初的老程序当初须要解决更大规模的问题;也可能是存在一个bug,音讯没有被及时处理,导致被沉积。如果没有思考缓冲区塞满时的对策,那么在将来的某个工夫就有可能呈现一个破坏性极强,隐蔽性极深且难以诊断的bug。最好的策略是在当初就思考如何解决缓存区被塞满的状况,将问题毁灭在萌芽阶段。因而罕用的缓存区类型有三种:阻塞型(blocking),弃用新值型(dropping),移出旧值型(sliding)
Python有什么消息传递并发模型?
Actor模型pykka:https://github.com/jodal/pykkaCSP模型pycsp:https://github.com/runefribor...
图片均来源于here!
参考:
- Communicating Sequential Processes (CSP)-An alternative to the actor model
- Concurrency Oriented Programming In Erlang-Joe Armstrong.pdf
记得帮我点赞哦!
精心整顿了计算机各个方向的从入门、进阶、实战的视频课程和电子书,依照目录正当分类,总能找到你须要的学习材料,还在等什么?快去关注下载吧!!!
朝思暮想,必有回响,小伙伴们帮我点个赞吧,非常感谢。
我是职场亮哥,YY高级软件工程师、四年工作教训,回绝咸鱼争当龙头的斜杠程序员。听我说,提高多,程序人生一把梭
如果有幸能帮到你,请帮我点个【赞】,给个关注,如果能顺带评论给个激励,将不胜感激。
职场亮哥文章列表:更多文章
自己所有文章、答复都与版权保护平台有单干,著作权归职场亮哥所有,未经受权,转载必究!