Erlang并发机制 – 消息传递

本文介绍了Erlang系统中进程间通信的核心机制——消息传递的过程。详细解释了消息复制的原因,以及在private堆内存架构下消息传递的具体步骤。同时探讨了不同堆内存架构的特点,以及Erlang如何优化消息队列的管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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中包括进程的消息队列,指向堆中的具体消息)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值