Erlang并发理解

时间:2015-10-16 17:15:02

标签: concurrency erlang server

最近我一直试图了解Erlang中的并发服务器。请考虑以下向服务器发出请求的代码。取决于 特定的执行顺序,3个过程可以打印不同的值。什么是订单以及每个流程的最高和最低价值是什么?

test() ->
    Server = start(),
    spawn(fun() ->
                  incr(Server),
                  io:format("Child 1 read ~p~n", [read(Server)]) end),
    incr(Server),
    spawn(fun() ->
                  incr(Server),
                  io:format("Child 2 read ~p~n", [read(Server)]) end),
    io:format("Parent read ~p~n", [read(Server)]).

代码针对以下服务器运行:

-module(p4).
-export([start/0, init/0, read/1, incr/1, reset/1]).

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

loop(N) ->
    receive
        {read, Pid} ->
            Pid ! {value, self(), N},
            loop(N);
        {incr, Pid} ->
            Pid ! {incr_reply, self()},
            loop(N+1);
        {reset, Pid} ->
            Pid ! {reset_reply, self()},
            loop(0)
    end.

read(Serv) ->
    Serv ! {read, self()},
    receive {value, Serv, N} -> N end.
incr(Serv) ->
    Serv ! {incr, self()},
    receive {incr_reply, Serv} -> ok end.
reset(Serv) ->
    Serv ! {reset, self()},
    receive {reset_reply, Serv} -> ok end.
  • 父级:最低= 1最高= 3
  • Child1:最低= 1最高= 3
  • Child2:最低= 1最高= 2

我不完全确定订单,但我想可能就是这样:

  • Child1可以阅读1,2和3
  • 家长可以阅读1,2和3
  • Child2可以阅读1和2

这对于最低,最高值和订单都是正确的吗?

1 个答案:

答案 0 :(得分:1)

循环中的初始值为0.服务器的递增操作在执行增量之前回复调用者,但这并不重要,因为在发送该回复和实际增量之间没有处理任何消息。每个读取消息都会产生一个回复,其中包含在其之前到达的所有增量消息的效果。由于保证从一个进程到另一个进程的消息排序,所以任何增加然后读取的进程都保证至少读取它自己的增量。服务器的读操作只是回复当前循环值。重置操作未使用。

Child1递增,然后读取。它最初与Parent同时运行,然后与Child2同时运行,两者也都递增。因此,它可以从它自己的增量中读取1,从它自己的增量中读取2,从它的父节点增加2,如果它的读取也从Child2中获取增量,则读取3。

Child2也会递增,然后读取,但在Parent已经递增之后才会启动。因此,它可以读取的最小值是2,因为它与Child1同时运行,所以它可以读取3。

父递增,然后读取,因此它可以读取的最小值是1.它的读取与Child1和Child2同时运行,因此如果它的读取发生在它们的任何一个增量之前,它会看到1.它可以选择读取2如果它的读取可以选择子项增量,如果读取了两个子项增量,则读取3。