问题描述
我想在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同时运行并将所有消息并发发送到服务器
。
父
进程执行以下顺序步骤:
- 生成
服务器
进程。最终将服务器
循环中的初始值设置为0
。 - 生成
Child1
。最终将2
的值写入Server
,然后从 - 使用
write / 2
发送值3
到服务器
。循环/ 1
函数中的写入
案例首先回复调用者,然后安装值3
。$>
- 使用
write2 / 2
发送5
到服务器
。write2 / 2
函数只是向服务器
发送消息,并且不等待回复。loop / 1
函数中的write2
案例只需安装值5
为其下一次迭代。 - 生成
Child2
,其中最终调用write2 / 2
,其值为1
,然后读取Server
并打印结果 - 读取
服务器
并打印结果。
对于 Parent
,步骤3将值 3
发送到服务器
,所以至于
。在步骤4中, Parent
,服务器
现在的值为$ code > 3 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 $之间交错写入消息c $ c>写入和阅读消息。
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 5Child1
: lowest 1, highest 5Child2
: 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:
- Spawns the
Server
process. This eventually sets the initial value in theServer
loop to0
. - Spawns
Child1
. This eventually writes the value2
toServer
, then reads fromServer
and prints the result. - Uses
write/2
to send the value3
toServer
. Thewrite
case in theloop/1
function first replies to the caller and then installs the value3
for its next iteration. - Uses
write2/2
to send5
toServer
. Thewrite2/2
function just sends a message toServer
and does not await a reply. Thewrite2
case in theloop/1
function just installs the value5
for its next iteration. - Spawns
Child2
, which eventually callswrite2/2
with the value1
, and then readsServer
and prints the result. - 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服务器请求订单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!