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
可以打印的最低值和最高值, Child1
和 Child2
进程。答案是:
Parent
: 最低 1,最高 5
Child1
: 最低 1,最高 5
Child2
: 最低 1,最高 2
有人可以解释一下吗?
请记住,Erlang 只保证从一个进程到另一个进程的消息顺序。如果进程 A 按顺序向进程 B 发送消息 1,然后再发送消息 2,则 B 将按此顺序接收它们。但是如果多个并发进程正在发送消息,Erlang 不保证到达 B 的消息的特定顺序。在此示例中,Parent
、Child1
和 Child2
都同时 运行,并且都同时向 Server
.
发送消息
Parent
进程执行以下顺序步骤:
- 生成
Server
进程。 最终 将 Server
循环中的初始值设置为 0
。
- 生成
Child1
。 最终 将值 2
写入 Server
,然后从 Server
读取并打印结果。
- 使用
write/2
将值3
发送到Server
。 loop/1
函数中的 write
案例首先回复调用者,然后为下一次迭代安装值 3
。
- 使用
write2/2
发送5
到Server
。 write2/2
函数只是向 Server
发送消息,并不等待回复。 loop/1
函数中的 write2
案例只是为其下一次迭代安装值 5
。
- 生成
Child2
,最终 使用值 1
调用 write2/2
,然后读取 Server
并打印结果。
- 读取
Server
并打印结果。
对于Parent
,第3步将值3
发送给Server
,所以就Parent
而言,Server
现在具有值3
。在第 4 步中,Parent
调用 write2/2
将 5
发送到服务器,并且该消息必须在第 3 步发送消息之后的某个时间到达 Server
。在第 6 步中, Parent
执行读取,但我们所知道的是此消息必须在步骤 4 中的写入消息之后到达 Server
。此消息排序意味着 Parent
可以看到的最高值是 5
.
Parent
可以看到的最低值是 1
因为如果 Child2
在 [=10= 之后得到它的写消息 1
到 Server
] 写 5
的消息但在最后 Parent
读取消息之前,然后 Parent
将看到 1
.
对于Child1
,它能看到的最高值是5
,因为它运行同时与Parent
和Parent
发送的两条消息可以在 2
的写入消息之前到达 Server
。最低的 Child1
可以看到的是 1
因为 1
的 Child2
写入消息可以在 Child1
读取消息之前到达。
对于Child2
,它能看到的最低值是它自己写的1
。它可以看到的最高值是 Child1
的写入中的 2
,因为 3
和 5
的 Parent
写入发生在 Child2
生成之前,因此 Child1
是唯一并发写入的进程,因此只有它有机会在 Child2
写入和读取消息之间交错其写入消息。
我试图理解 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
可以打印的最低值和最高值, Child1
和 Child2
进程。答案是:
Parent
: 最低 1,最高 5Child1
: 最低 1,最高 5Child2
: 最低 1,最高 2
有人可以解释一下吗?
请记住,Erlang 只保证从一个进程到另一个进程的消息顺序。如果进程 A 按顺序向进程 B 发送消息 1,然后再发送消息 2,则 B 将按此顺序接收它们。但是如果多个并发进程正在发送消息,Erlang 不保证到达 B 的消息的特定顺序。在此示例中,Parent
、Child1
和 Child2
都同时 运行,并且都同时向 Server
.
Parent
进程执行以下顺序步骤:
- 生成
Server
进程。 最终 将Server
循环中的初始值设置为0
。 - 生成
Child1
。 最终 将值2
写入Server
,然后从Server
读取并打印结果。 - 使用
write/2
将值3
发送到Server
。loop/1
函数中的write
案例首先回复调用者,然后为下一次迭代安装值3
。 - 使用
write2/2
发送5
到Server
。write2/2
函数只是向Server
发送消息,并不等待回复。loop/1
函数中的write2
案例只是为其下一次迭代安装值5
。 - 生成
Child2
,最终 使用值1
调用write2/2
,然后读取Server
并打印结果。 - 读取
Server
并打印结果。
对于Parent
,第3步将值3
发送给Server
,所以就Parent
而言,Server
现在具有值3
。在第 4 步中,Parent
调用 write2/2
将 5
发送到服务器,并且该消息必须在第 3 步发送消息之后的某个时间到达 Server
。在第 6 步中, Parent
执行读取,但我们所知道的是此消息必须在步骤 4 中的写入消息之后到达 Server
。此消息排序意味着 Parent
可以看到的最高值是 5
.
Parent
可以看到的最低值是 1
因为如果 Child2
在 [=10= 之后得到它的写消息 1
到 Server
] 写 5
的消息但在最后 Parent
读取消息之前,然后 Parent
将看到 1
.
对于Child1
,它能看到的最高值是5
,因为它运行同时与Parent
和Parent
发送的两条消息可以在 2
的写入消息之前到达 Server
。最低的 Child1
可以看到的是 1
因为 1
的 Child2
写入消息可以在 Child1
读取消息之前到达。
对于Child2
,它能看到的最低值是它自己写的1
。它可以看到的最高值是 Child1
的写入中的 2
,因为 3
和 5
的 Parent
写入发生在 Child2
生成之前,因此 Child1
是唯一并发写入的进程,因此只有它有机会在 Child2
写入和读取消息之间交错其写入消息。