You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Erlang gen_server是否不能调用自身API?书中表述与示例代码矛盾疑问

你的理解存在偏差,二者不存在矛盾,核心区别在于调用的目标进程、调用类型和触发场景。

先明确书里提示的死锁触发前提

服务端不能调用自身的API函数,特指tr_server进程在自身回调逻辑执行过程中,主动发起对自己的同步gen_server:call请求

gen_server的所有回调(handle_info/2、handle_call/3、handle_cast/2等)都是串行执行的,同一时间只会运行一个回调逻辑,新接收的消息会暂存到进程邮箱排队,等当前回调执行完成后才会取出下一条处理。
如果在handle_info/2的执行过程中调用tr_server:get_count(),会触发gen_server:call(?SERVER, get_count):

  • 首先会给tr_server进程(就是当前正在执行回调的进程自身)的邮箱塞一条call消息
  • 之后gen_server:call会进入阻塞等待状态,等待目标进程返回结果
    但此时tr_server进程还卡在handle_info/2的执行逻辑里,根本不会去处理邮箱里刚塞入的call消息,永远等不到返回,最终形成死锁。

再看示例代码的逻辑,和提示完全一致

示例中的do_rpc是处理客户端发来的RPC请求,执行apply(M,F,A)的时候分三种场景:

  • 调用其他服务/普通模块的函数:完全没有问题,不涉及自身进程的调用,不会触发死锁
  • 调用tr_server自身的异步API(比如tr_server:stop/0,内部是gen_server:cast):不会死锁,因为cast是异步操作,只负责把消息塞到自身邮箱,不会阻塞等待返回,当前handle_info/2执行完成后,就会自动取出cast消息处理
  • 调用tr_server自身的同步API(也就是书里明确列为例外的tr_server:get_count/0):确实会触发死锁,这也是为什么书里专门强调这个接口不允许被RPC调用,属于明确禁止的例外场景,和提示完全吻合,不存在矛盾。

内容的提问来源于stack exchange,提问作者gy l

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 10:36:04