gpt4 book ai didi

concurrency - 如果在发出进程 pid 之前向进程发送消息,是否保证首先收到该消息?

转载 作者:行者123 更新时间:2023-12-04 02:44:14 24 4
gpt4 key购买 nike

说有个进程B ,它接收一个 pid 并发送 m2到它。如果您生成 A并发送 m1 ,然后发送 AB , 是 A保证得到m1之前 m2 ?

换句话说,这会崩溃吗?

-module(test).
-compile(export_all).

test() ->
B = spawn_link(fun() -> receive P -> P ! m2 end end),
A = spawn_link(fun() -> receive X -> X=m1 end end),
A ! m1,
B ! A.

最佳答案

您的代码不会崩溃,因为 所有进程都是本地的 .

B = spawn_link(fun() -> receive P -> P ! m2 end end),     % 1
A = spawn_link(fun() -> receive X -> X=m1 end end), % 2
A ! m1, % 3
B ! A. % 4

在评估第 3 行时,BEAM 模拟器和 HiPE 都会调用 erl_send内置函数 (BIF)。由于 A 是一个本地进程, erl_send (实际上是 do_send )最终会调用 erts_send_message其中 enqueues邮箱中的消息。在 SMP 模式下,线程实际上获取邮箱上的锁。

因此,当评估第 4 行并将 A 发送到进程 B 时,A 的邮箱中已经有 m1。所以 m2只能在 m1 之后排队.

这个结果是否是 Erlang 的当前实现的特殊性是有争议的,即使文档不能保证这一点。确实,每个进程都需要一个邮箱,而这个邮箱需要以某种方式填充。这是在第 3 行同步完成的。要异步完成,需要在中间的另一个线程或每个进程几个邮箱(例如,每个调度程序一个,以避免邮箱上的锁定)。然而,我认为这在性能方面没有意义。

如果处理 A 和 B 位于远程但在同一节点内 ,行为略有不同,但结果将与 Erlang 的当前实现相同。第 3 行,留言 m1将排入远程节点的队列,并在第 4 行,消息 A之后会排队。当远程节点将消息出列时,它会先写 m1写信前到A的邮箱 A到 B 的邮箱。

如果处理 A 是远程的,B 是本地的 ,结果还是一样。第 3 行,留言 m1将排队等待远程节点,在第 4 行,消息将写入 B,但在第 1 行,消息 m2将在 m1 之后排队到远程节点.所以 A 将按 m1、m2 的顺序获取消息。

同样,如果处理 A 是本地的,B 是远程的 , A 将在第 3 行将消息复制到其邮箱,然后再通过网络将任何内容发送到 B 的节点。

使用当前版本的 Erlang,崩溃的唯一方法是使用 A 和 B 位于不同的远程节点 .在这种情况下, m1A 之前排队到 A 的节点排队到 B 的节点。但是,这些消息的传递不是同步的。传送到 B 的节点可能首先发生,例如,如果许多消息已经排队等待 A 的节点。

以下代码(有时)通过用垃圾消息填充队列到 A 的节点来触发崩溃,这些垃圾消息会减慢 m1 的传递速度。 .
$ erl -sname node_c@localhost
C = spawn_link(fun() ->
A = receive {process_a, APid} -> APid end,
B = receive {process_b, BPid} -> BPid end,
ANode = node(A),
lists:foreach(fun(_) ->
rpc:cast(ANode, erlang, whereis, [user])
end, lists:seq(1, 10000)),
A ! m1,
B ! A
end),
register(process_c, C).
$ erl -sname node_b@localhost
B = spawn_link(fun() -> receive P -> P ! m2 end end),
C = rpc:call(node_c@localhost, erlang, whereis, [process_c]),
C ! {process_b, B}.
$ erl -sname node_a@localhost
A = spawn_link(fun() -> receive X -> X = m1 end, io:format("end of A\n") end),
C = rpc:call(node_c@localhost, erlang, whereis, [process_c]),
C ! {process_a, A}.

关于concurrency - 如果在发出进程 pid 之前向进程发送消息,是否保证首先收到该消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18018780/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com