`
jzhihui
  • 浏览: 266038 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Erlang并发机制 – 消息传递

阅读更多

Erlang系统中,进程之间的通信是通过消息传递来完成的。消息使用Pid ! Message的形式发送,通过receive语句获取。每个Erlang进程都有用来存储传入消息的信箱。当一个消息发送的时候,它会从发送进程中拷贝到接收进程的信箱,并以它们到达的时间次序存储。消息的传递是异步的,一个发送进程不会在发送消息后被暂停。

 

         上面提到发送消息时,会在两个进程之间存在消息复制,为什么需要复制呢?这就跟进程的堆内存有关。虽然在Erlang文档heap_type)中说明堆内存有三种类型:privatesharedhybrid,但是在实际的代码中,只有两种privatehybrid(参见[$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类型的堆内存是指每个进程独享一块内存,对于内存的访问不需要锁保护。

        

Erlangprivate堆内存架构下,发送消息需要做三件事件:

         1) 计算消息的大小,并在接收进程的内存空间中给消息分配内存;

         2) 将消息的内容拷贝到接收进程的堆内存中;

         3) 最后将消息的地址添加到接收进程的消息队列。

从上面的步骤可以看出,拷贝消息的代码是O(n)n是消息的长度,也就是说消息越长,花费越大。所以在使用Erlang时,要避免大数据量的大消息传递。

shared堆内存架构下,发送消息只需要O(1)(只传递消息地址),那为什么Erlang要默认选择private类型的堆内存呢?其实这跟后面要讲到的ErlangGC相关:private的优势就是GC的延迟很低,可以很快的完成(因为只保存一个进程的数据,GC扫描时的数据量很小)。

         SMP环境下,实际上每个进程有两个消息队列。进程发送消息时,实际上消息是添加到目标进程的公有队列(通过锁来保证互斥访问);而目标进程在消费消息时,实际上是在自己的私有消息队列上处理的,从而减小锁带来的访问开销。但是,如果目标进程在自己的私有消息队列上无法匹配到消息,那么公有队列中的消息将被添加到私有队列。

         下图是比较直观的说明了消息发送前后的进程数据的对比(其中PCB中包括进程的消息队列,指向堆中的具体消息)。

  • 大小: 38.7 KB
1
0
分享到:
评论
2 楼 jzhihui 2013-04-11  
AsIMovedon 写道
不错。最后一张图after send后为什么多出了一块三角形数据?


原来的消息共享子内容,发送到P2后不再共享
1 楼 AsIMovedon 2013-04-10  
不错。最后一张图after send后为什么多出了一块三角形数据?

相关推荐

Global site tag (gtag.js) - Google Analytics