Erlang:退出/关闭同步还是异步?

时间:2014-12-12 18:05:59

标签: asynchronous process erlang signals synchronous

您有一个要杀死的进程树,因此您向主管发送退出(PID,关闭)。还有其他需要做的事情,但在关闭此进程树之前无法完成。例如,假设此进程树写入数据库。你想干净地关闭所有东西。您想要关闭数据库,但显然您需要先关闭进程树,否则树可能正在写入数据库。

我的问题是,当我发送退出信号时,是同步还是异步?如果它是同步的,似乎我没有后顾之忧,但是如果它是异步的,我将需要做一些事情,比如建立一个进程监视器并在我继续数据库关闭之前检查树是否关闭,对吗?

感谢。

2 个答案:

答案 0 :(得分:1)

简短回答:OTP关闭是同步的。 exit / 2是一个异步消息。

答案很长:Erlang中的所有消息都是异步的。关机消息也不例外。但是,关闭不仅仅是发送消息。主管在发送退出信号后侦听{'DOWN', ...}消息。只有在收到“DOWN”消息或超时后才会继续,所以实际上它是同步的。查看主管源代码。在第894行是定义实际进行退出调用的函数的地方:

shutdown(Pid, Time) ->
case monitor_child(Pid) of
ok ->
    exit(Pid, shutdown), %% Try to shutdown gracefully
    receive 
    {'DOWN', _MRef, process, Pid, shutdown} ->
        ok;
    {'DOWN', _MRef, process, Pid, OtherReason} ->
        {error, OtherReason}
    after Time ->
        exit(Pid, kill),  %% Force termination.
        receive
        {'DOWN', _MRef, process, Pid, OtherReason} ->
            {error, OtherReason}
        end
    end;
{error, Reason} ->      
    {error, Reason}
end.

可以在GitHub上查看源代码:https://github.com/erlang/otp/blob/maint/lib/stdlib/src/supervisor.erl#L894

另一方面,

erlang:exit/2调用只是一个异步退出信号

答案 1 :(得分:1)

如果您需要自己管理,请自行监控:

sneak_attack(BankGuard) ->
    monitor(process, BankGuard),
    exit(BankGuard, kill),
    Cash = receive {'DOWN', _, process, BankGuard, _} -> rob_bank() end,
    send_to_bahamas(Cash).

在此示例中,rob_bank()及其他任何内容被阻止等待来自BankGuard的'DOWN'消息。

另外,请注意,这是一个更通用的概念,而不仅仅是关闭某些东西。 Erlang中的所有消息都是异步的,但与UDP不同,订购(在两个进程之间)和交付(只要目标处于活动状态)是有保证的。因此,同步消息传递只是监视目标,发送标记消息,并在收到返回消息时阻塞。