Erlang并发机制 – 消息传递
来源:互联网 发布:js 水球图 编辑:程序博客网 时间:2024/06/06 03:07
Erlang系统中,进程之间的通信是通过消息传递来完成的。消息使用Pid ! Message的形式发送,通过receive语句获取。每个Erlang进程都有用来存储传入消息的信箱。当一个消息发送的时候,它会从发送进程中拷贝到接收进程的信箱,并以它们到达的时间次序存储。消息的传递是异步的,一个发送进程不会在发送消息后被暂停。
上面提到发送消息时,会在两个进程之间存在消息复制,为什么需要复制呢?这就跟进程的堆内存有关。虽然在Erlang的文档(heap_type)中说明堆内存有三种类型:private,shared,hybrid,但是在实际的代码中,只有两种private和hybrid(参见[$R15B_OTP_SRC/erts/emulator/beam/erl_bif_info.c --> system_info_1]),不过hybrid的虚拟机是编译不出来的(参见[$R15B_OTP_SRC/erts/Makefile.in:# Until hybrid is nofrag, don't build it.),也就是说Erlang目前的堆内存只有一种:private。
private类型的堆内存是跟shared类型相对的:shared是指所有线程共享同一块内存(比如Java),多个线程对同一块内存的访问需要锁保护;而private类型的堆内存是指每个进程独享一块内存,对于内存的访问不需要锁保护。
在Erlang的private堆内存架构下,发送消息需要做三件事件:
1) 计算消息的大小,并在接收进程的内存空间中给消息分配内存;
2) 将消息的内容拷贝到接收进程的堆内存中;
3) 最后将消息的地址添加到接收进程的消息队列。
从上面的步骤可以看出,拷贝消息的代码是O(n),n是消息的长度,也就是说消息越长,花费越大。所以在使用Erlang时,要避免大数据量的大消息传递。
在shared堆内存架构下,发送消息只需要O(1)(只传递消息地址),那为什么Erlang要默认选择private类型的堆内存呢?其实这跟后面要讲到的Erlang的GC相关:private的优势就是GC的延迟很低,可以很快的完成(因为只保存一个进程的数据,GC扫描时的数据量很小)。
在SMP环境下,实际上每个进程有两个消息队列。进程发送消息时,实际上消息是添加到目标进程的公有队列(通过锁来保证互斥访问);而目标进程在消费消息时,实际上是在自己的私有消息队列上处理的,从而减小锁带来的访问开销。但是,如果目标进程在自己的私有消息队列上无法匹配到消息,那么公有队列中的消息将被添加到私有队列。
下图是比较直观的说明了消息发送前后的进程数据的对比(其中PCB中包括进程的消息队列,指向堆中的具体消息)。
- Erlang并发机制 – 消息传递
- Erlang并发机制 – 消息传递
- Erlang并发编程之消息传递
- Golang和Erlang消息传递机制对比
- Erlang并发机制 –进程调度
- Erlang并发机制 –进程调度
- Erlang并发机制 –进程调度
- 16.5 消息并发传递
- Window消息传递机制
- Window消息传递机制
- VC消息传递机制
- ipanel 消息传递机制
- Handler消息传递机制
- Handler 消息传递机制
- Window消息传递机制
- Handler消息传递机制
- Handler消息传递机制
- Handler 消息传递机制
- hello blog
- 永乐大帝二世:这个时代“寒门再难出贵子”(文摘)
- 关于JAVA排序的一些
- 【代码生成】sqlserver系统表说明
- JavaScript 零碎知识点整理(一)
- Erlang并发机制 – 消息传递
- 将jar文件与dex文件的转换
- WPF(5)----文件浏览对话框
- Ubuntu 12.04 无法关机的解决办法-acer4750 ubuntu12.04 32验证失败
- 目标驱动器中的磁盘已满
- 一个发人深省的经典理财故事
- eclipse 中运行参数设置
- make mex compiler of matlab working on gcc mint
- 关于取列表排序段的指定段思路