本文介绍了Erlang服务器请求订单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在erlang中了解请求的顺序,但我看起来好像不太了解。以下是示例代码:

  test() - > 
Server = start(),
spawn(fun() - > write(Server,2),
io:format(Child 1 read〜p〜n,[read服务器)])结束)​​
写(服务器,3),
write2(服务器,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() - >环(0)。

loop(N) - >
收到
{读,Pid} - >
P! {value,self(),N},
loop(N);
{write,Pid,M} - >
P! {write_reply,self()},
loop(M);
{write2,_Pid,M} - >循环(M)
结束。

read(Serv) - >
服务! {read,self()},
receive {value,Serv,N} - > N结束。

write(Serv,N) - >
服务! {write,self(),N},
receive {write_reply,Serv} - >好的结束

write2(Serv,N) - >
服务! {write2,self(),N},
ok。

我明白,在中创建的三个不同进程可以打印不同的值test / 0 ,但是我试图找出可以由 Parent , Child1 和 Child2 进程。答案是:




  • 父母:最低1,最高5

  • Child1 :最低1,最高5

  • Child2 :最低1,最高2



有人可以解释一下吗

解决方案

请记住,Erlang仅保证从一个进程到另一个进程的消息顺序。如果进程A顺序地发送消息1,然后将消息2发送到进程B,则B将按照该顺序接收它们。但是如果多个并发进程正在发送它们,Erlang就不会保证到达B的消息的具体顺序。在这个例子中, Parent Child1 Child2 all同时运行并将所有消息并发发送到服务器



进程执行以下顺序步骤:


  1. 生成服务器进程。最终将服务器循环中的初始值设置为 0

  2. 生成 Child1 。最终将 2 的值写入 Server ,然后从 并打印结果。

  3. 使用 write / 2 发送值 3 服务器循环/ 1 函数中的写入案例首先回复调用者,然后安装值 3
  4. 使用 write2 / 2 发送 5 服务器 write2 / 2 函数只是向服务器发送消息,并且不等待回复。 loop / 1 函数中的 write2 案例只需安装值 5 为其下一次迭代。

  5. 生成 Child2 ,其中最终调用 write2 / 2 ,其值为 1 ,然后读取 Server 并打印结果

  6. 读取服务器并打印结果。

对于 Parent ,步骤3将值 3 发送到服务器,所以至于 Parent 服务器现在的值为$ code > 3 。在步骤4中, Parent 调用 write2 / 2 发送 5 到服务器,并且该消息必须在步骤3中发送消息之后的某个时刻到达服务器。在步骤6中,执行读取,但是我们知道的是,该消息必须在步骤4中的写消息之后到达服务器。该消息排序意味着最高值父母可以看到是 5



最低值 Parent 可以看到是 1 ,因为如果 Child2 获得其写入消息 1 服务器之后 Parent 写入消息 5 ,但在最终 Parent 阅读消息之前,则 Parent 将会看到 1



对于 Child1 ,最高价值可以看到是 5 ,因为它与 Parent 同时运行,由 Parent 可以到达服务器之前写入消息 2 。 $ code> Child1 可以看到是 1 ,因为 Child2 1 的消息可以在 Child1 阅读消息之前到达。



对于 Child2 ,可以看到的最低值是它自己写的 1 。可以看到的最高价值是 2 Child1 的写入,因为 Parent 写入 3 5 发生在 Child2 被生成,因此 Child1 是同时写入的唯一过程,因此只有它有可能在 Child2 写入和阅读消息。


I'm trying to understand request order in erlang, but I can't seem to grasp it very well. Here's the example code:

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)]).

And here's the 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.

I understand that different values could be printed by the three different processes created in test/0, but I'm trying to figure out the lowest and highest values that could be printed by those Parent, Child1 and Child2 processes. The answer states:

  • Parent: lowest 1, highest 5
  • Child1: lowest 1, highest 5
  • Child2: lowest 1, highest 2

Can somebody explain this?

解决方案

Keep in mind that Erlang guarantees message order only from one process to another. If process A sequentially sends message 1 and then message 2 to process B, then B will receive them in that order. But Erlang guarantees no specific ordering of messages arriving at B if multiple concurrent processes are sending them. In this example, Parent, Child1, and Child2 all run concurrently and all send messages concurrently to Server.

The Parent process performs the following sequential steps:

  1. Spawns the Server process. This eventually sets the initial value in the Server loop to 0.
  2. Spawns Child1. This eventually writes the value 2 to Server, then reads from Server and prints the result.
  3. Uses write/2 to send the value 3 to Server. The write case in the loop/1 function first replies to the caller and then installs the value 3 for its next iteration.
  4. Uses write2/2 to send 5 to Server. The write2/2 function just sends a message to Server and does not await a reply. The write2 case in the loop/1 function just installs the value 5 for its next iteration.
  5. Spawns Child2, which eventually calls write2/2 with the value 1, and then reads Server and prints the result.
  6. Reads Server and prints the result.

For Parent, step 3 sends the value 3 to Server, so as far as Parent is concerned, Server now has the value 3. In step 4, Parent calls write2/2 to send 5 to the server, and that message must arrive at Server sometime after the message sent in step 3. In step 6, Parent performs a read, but all we know is that this message has to arrive at Server after the write message in step 4. This message ordering means the highest value Parent can see is 5.

The lowest value Parent can see is 1 because if Child2 gets its write message of 1 to Server after the Parent write message of 5 but before the final Parent read message, then Parent will see the 1.

For Child1, the highest value it can see is 5 because it runs concurrently with Parent and the two messages sent by Parent could arrive at Server before its write message of 2. The lowest Child1 can see is 1 because the Child2 write message of 1 can arrive before the Child1 read message.

For Child2, the lowest value it can see is its own write of 1. The highest value it can see is 2 from the write of Child1 because the Parent writes of 3 and 5 occur before Child2 is spawned, thus Child1 is the only process writing concurrently and so only it has a chance of interleaving its write message between the Child2 write and read messages.

这篇关于Erlang服务器请求订单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 17:31