Erlang 服务器请求顺序

Erlang server request order

我试图理解 erlang 中的请求顺序,但我似乎无法很好地掌握它。这是示例代码:

test() ->
    Server  = start(),
    spawn(fun() -> write(Server, 2),
                   io:format(”Child 1 read ~p~n”, [read(Server)]) end),
    write(Server, 3),
    write2(Server, 5),
    spawn(fun() -> write2(Server, 1),
                   io:format(”Child 2 read  ~p~n”, [read(Server)]) end),
    io:format(”Parent read ~p~n”, [read(Server)]).

这是服务器:

start() ->
    spawn(fun() -> init() end).

init() -> loop(0).

loop(N) ->
    receive
        {read, Pid} ->
            Pid ! {value, self(), N},
            loop(N);
        {write, Pid, M} ->
            Pid ! {write_reply, self()},
            loop(M);
        {write2, _Pid, M} -> loop(M)
    end.

read(Serv) ->
    Serv ! {read, self()},
    receive {value, Serv, N} -> N end.

write(Serv, N) ->
    Serv ! {write, self(), N},
    receive {write_reply, Serv} -> ok end.

write2(Serv, N) ->
    Serv ! {write2, self(), N},
    ok.

我知道 test/0 中创建的三个不同进程可以打印不同的值,但我试图找出那些 Parent 可以打印的最低值和最高值, Child1Child2 进程。答案是:

有人可以解释一下吗?

请记住,Erlang 只保证从一个进程到另一个进程的消息顺序。如果进程 A 按顺序向进程 B 发送消息 1,然后再发送消息 2,则 B 将按此顺序接收它们。但是如果多个并发进程正在发送消息,Erlang 不保证到达 B 的消息的特定顺序。在此示例中,ParentChild1Child2 都同时 运行,并且都同时向 Server.

发送消息

Parent 进程执行以下顺序步骤:

  1. 生成 Server 进程。 最终Server 循环中的初始值设置为 0
  2. 生成 Child1最终 将值 2 写入 Server,然后从 Server 读取并打印结果。
  3. 使用write/2将值3发送到Serverloop/1 函数中的 write 案例首先回复调用者,然后为下一次迭代安装值 3
  4. 使用write2/2发送5Serverwrite2/2 函数只是向 Server 发送消息,并不等待回复。 loop/1 函数中的 write2 案例只是为其下一次迭代安装值 5
  5. 生成 Child2最终 使用值 1 调用 write2/2,然后读取 Server 并打印结果。
  6. 读取 Server 并打印结果。

对于Parent,第3步将值3发送给Server,所以就Parent而言,Server现在具有值3。在第 4 步中,Parent 调用 write2/25 发送到服务器,并且该消息必须在第 3 步发送消息之后的某个时间到达 Server。在第 6 步中, Parent 执行读取,但我们所知道的是此消息必须在步骤 4 中的写入消息之后到达 Server。此消息排序意味着 Parent 可以看到的最高值是 5.

Parent 可以看到的最低值是 1 因为如果 Child2 在 [=10= 之后得到它的写消息 1Server ] 写 5 的消息但在最后 Parent 读取消息之前,然后 Parent 将看到 1.

对于Child1,它能看到的最高值是5,因为它运行同时与ParentParent发送的两条消息可以在 2 的写入消息之前到达 Server。最低的 Child1 可以看到的是 1 因为 1Child2 写入消息可以在 Child1 读取消息之前到达。

对于Child2,它能看到的最低值是它自己写的1。它可以看到的最高值是 Child1 的写入中的 2,因为 35Parent 写入发生在 Child2 生成之前,因此 Child1 是唯一并发写入的进程,因此只有它有机会在 Child2 写入和读取消息之间交错其写入消息。