您好我正在通过了解一些基本的Erlang服务器模块来进行一些Erlang培训。但是我被困在这一个。在这个模块中,我应该告诉3个进程(父进程和2个进程)中每个进程可以打印的最低和最高可能值,因为根据特定的执行顺序,3个进程可以打印不同的值。 / p>
我执行了测试并为父级获得了2,为两个子进程获得了3,但我不知道他们是如何获得这些值的。有人可以专门向我解释这个过程吗?赞赏。
这是模块:
-module(p4).
-export([start/0, init/0, read/1, incr/1, reset/1, test/0]).
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.
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)]).
答案 0 :(得分:2)
理解Lukasz答案的一个精度是所有服务器接口(读取,加载,重置)都是同步的:它们等待来自服务器的答案。这意味着在服务器完成请求之前,使用这些接口的进程无法执行任何操作。认为child2读数不能低于2是非常重要的。
2个序列图,用于可视化过程:
答案 1 :(得分:1)
尝试打印正在接收的任何消息服务器(或使用调试器跟踪)以便更好地理解,您应该得到类似的内容:
Server state was: 0 and received: {incr,<0.59.0>}
Server state was: 1 and received: {incr,<0.109.0>}
Server state was: 2 and received: {read,<0.59.0>}
Server state was: 2 and received: {incr,<0.110.0>}
Parent read 2
Server state was: 3 and received: {read,<0.109.0>}
Server state was: 3 and received: {read,<0.110.0>}
Child 1 read 3
child 2 read 3
<0.59.0>
是父流程,<0.109.0>
是子1,<0.110.0>
是子2。
这意味着在read
子进程之前,但在第一个子read
之后传递了父incr
条消息。但它不一定是这样的。这取决于进程安排。您唯一的保证是从进程A发送到进程B的消息将以相同的顺序传递。
由于incr(Server)
和read(Server)
的同步特性,它并不重要。因为每个进程在incr(Server)
之前运行read(Server)
它必须至少得到1但是请注意,在父执行incr(Server)
之后生成了子2,这是同步操作所以它必须至少为1时它运行自己的incr(Server)
,所以当它读取时它必须至少为2.每个值的最大值为3(incr(Server)
的总数,表示每个read(Server)
他们可能会被推迟)。
可能的印刷值摘要:父母:1,2,3;孩子1:1,2,3;孩子2:2,3
简化执行顺序:
你的情况(父母得到2,两个孩子都得3):
parent: spawn server
parent: spawn child 1
parent: incr(Server)
child 1: incr(Server)
parent: spawn child 2
parent: io:format("parent read ~p~n",[read(Server)]) % prints 2
child 2: incr(Server)
child 1: parent: io:format("child 1 read ~p~n",[read(Server)]) % prints 3
child 2: parent: io:format("child 2 read ~p~n",[read(Server)]) % prints 3
儿童1的最低限度案例:
parent: spawn server
parent: spawn child 1
child 1: incr(Server)
child 1: io:format("child 1 read ~p~n",[read(Server)]) % prints 1
...
父母的最大案例:
parent: spawn server
parent: spawn child 1
parent: incr(Server)
parent: spawned child 2
child 1: incr(Server)
child 2: incr(Server)
Parent: io:format("child 1 read ~p~n",[read(Server)]) % prints 3
...
我已经创建了大量测试,它产生了100000个同时运行test/0
的进程,并创建了外部stat_server
,它获取并计算每个进程read(Server)
resault,这里是:
[{{child1,1},2}, % child 1 reads 1 only twice. Sometimes it's 1 sometimes it's 0, it varies
{{child1,2},53629},
{{child1,3},46369},
{{child2,2},107},
{{child2,3},99893},
{{parent,1},855},
{{parent,2},99112},
{{parent,3},33}]