Erlang代码理解

Erlang代码理解,erlang,concurrent-programming,Erlang,Concurrent Programming,您好,我正在通过了解一些基本的Erlang服务器模块来进行Erlang培训。然而,我在这个问题上陷入了困境。在本模块中,我应该告诉3个进程(父进程和2个子进程)中的每个进程可以打印的最低和最高值,因为根据特定的执行顺序,3个进程可能打印不同的值 我执行了测试,父进程得到2,两个子进程都得到3,但我不知道它们是如何得到这些值的。有人能具体地向我解释一下这个过程吗?谢谢 以下是模块: -模块(p4)。 -导出([start/0、init/0、read/1、incr/1、reset/1、test/0

您好,我正在通过了解一些基本的Erlang服务器模块来进行Erlang培训。然而,我在这个问题上陷入了困境。在本模块中,我应该告诉3个进程(父进程和2个子进程)中的每个进程可以打印的最低和最高值,因为根据特定的执行顺序,3个进程可能打印不同的值

我执行了测试,父进程得到2,两个子进程都得到3,但我不知道它们是如何得到这些值的。有人能具体地向我解释一下这个过程吗?谢谢

以下是模块:

-模块(p4)。
-导出([start/0、init/0、read/1、incr/1、reset/1、test/0])。
开始()->
繁殖(fun()->init()结束)。
init()->循环(0)。
循环(N)->
接收
{read,Pid}->
Pid!{value,self(),N},
环(N);
{incr,Pid}->
Pid!{incr_reply,self()},
环(N+1);
{reset,Pid}->
Pid!{reset_reply,self()},
循环(0)
结束。
阅读(服务)->
服务员!{read,self()},
接收{value,Serv,N}->N结束。
增量(服务)->
服务员!{incr,self()},
接收{incr_reply,Serv}->确定结束。
重置(服务)->
服务员!{reset,self()},
接收{reset_reply,Serv}->确定结束。
测试()->
Server=start(),
繁殖(fun()->incr(服务器),
io:格式(“子1读取~p~n”,[read(Server)]结束),
增量(服务器),
繁殖(fun()->incr(服务器),
io:格式(“子2读取~p~n”,[read(Server)]结束),
io:格式(“父读取~p~n”,[read(Server)]。

尝试打印服务器接收到的任何消息(或使用调试器跟踪),以便更好地理解,您应该得到如下信息:

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
儿童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\u服务器
,它获取并统计每个进程的读取(服务器)结果,如下所示:

[{{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}]

尝试打印服务器正在接收的任何消息(或使用调试器跟踪),以便更好地理解,您应该得到如下信息:

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
儿童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\u服务器
,它获取并统计每个进程的读取(服务器)结果,如下所示:

[{{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}]

尝试打印服务器正在接收的任何消息(或使用调试器跟踪),以便更好地理解,您应该得到如下信息:

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
儿童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\u服务器
,它获取并统计每个进程的读取(服务器)结果,如下所示:

[{{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}]

尝试打印服务器正在接收的任何消息(或使用调试器跟踪),以便更好地理解,您应该得到如下信息:

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
儿童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\u服务器
,它获取并统计每个进程的读取(服务器)结果,如下所示:

[{{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}]

理解Lukasz的答案的一个精度是,所有服务器接口(read、incr、reset)都是同步的:它们等待来自服务器的答案。这意味着在服务器完成请求之前,使用这些接口的进程无法执行任何操作。证明child2不能阅读少于2的内容是非常重要的

2个顺序图,以可视化流程:


理解卢卡斯答案的一个精确点是,所有服务器接口(读取、增量、重置)都是同步的:它们等待服务器的回答。这意味着在服务器完成请求之前,使用这些接口的进程无法执行任何操作。证明child2不能阅读少于2的内容是非常重要的

2个顺序图,以可视化流程:


理解卢卡斯答案的一个精确点是,所有服务器接口(读取、增量、重置)都是同步的:它们等待服务器的回答。这意味着在服务器完成请求之前,使用这些接口的进程无法执行任何操作。证明child2不能阅读少于2的内容是非常重要的

2个顺序图,以可视化流程:


理解卢卡斯答案的一个精确点是,所有服务器接口(读取、增量、重置)都是同步的:它们等待服务器的回答。这意味着在服务器完成请求之前,使用这些接口的进程无法执行任何操作。证明child2不能阅读少于2的内容是非常重要的

2个顺序图,以可视化流程:


您能告诉我哪些行指定在同一进程的消息A之后发送的消息B将在A之后发送到目标进程吗?以及为什么每个进程在读取之前发送
incr
?@user1579701每个进程在读取之前运行incr(服务器)。看看read/1的定义。Spawn函数仅创建新进程。它不会等到完成或开始传递函数执行时才执行。@user1579701刚刚注意到我在读取子2的最小值时犯的错误。编辑了我的答案。您能告诉我哪些行指定在同一进程的消息A之后发送的消息B将在A之后传递到目标进程吗?以及为什么每个进程在读取之前发送
incr
?@user1579701每个进程在读取之前运行incr(服务器)。看看read/1的定义。Spawn函数仅创建新进程。它不会等到完成或开始