2014-12-28 4 views
0

안녕하세요 저는 몇 가지 기본 얼랭 (Erlang) 서버 모듈을 이해하여 얼랭 트레이닝을하고 있습니다. 그러나 나는 이것에 붙어있다. 이 모듈에서는 3 개의 프로세스 (부모 프로세스와 2 개의 자식 프로세스) 각각이 인쇄 할 수있는 가장 낮은 값과 가장 높은 값을 알려주고 있습니다. 실행 순서에 따라 3 개의 프로세스가 다른 값을 인쇄 할 수 있기 때문입니다.얼랭 코드 이해

테스트를 실행하고 부모 프로세스 2 개, 하위 프로세스 프로세스 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} -> 
 
\t  Pid ! {value, self(), N}, 
 
\t  loop(N); 
 
\t {incr, Pid} -> 
 
      Pid ! {incr_reply, self()}, 
 
\t  loop(N+1); 
 
\t {reset, Pid} -> 
 
      Pid ! {reset_reply, self()},  
 
\t  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. 
 
\t  
 
test() -> \t 
 
    Server = start(), 
 
    spawn(fun() -> incr(Server), 
 
\t \t io:format("Child 1 read ~p~n", [read(Server)]) end), 
 
    incr(Server), 
 
    spawn(fun() -> incr(Server), 
 
\t   io:format("child 2 read ~p~n", [read(Server)]) end), 
 
    io:format("Parent read ~p~n", [read(Server)]). 
 
\t \t

답변

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)을 실행하기 때문에 적어도 1을 가져야 만하지만 부모가 incr(Server)을 실행 한 후에 자식 2가 생성되었으므로 동기 작업이므로 incr(Server)을 실행할 때 1 이상이어야하므로 읽어야합니다. 각각의 최대 값은 3입니다 (전체 숫자는 incr(Server)이며 이는 각각 read(Server)이 지연 될 수 있음을 의미 함).

가능한 인쇄 된 값의 요약 : 부모 : 1,2,3; 아이 1 : 1,2,3; 자녀 2 : 2,3

의 단순화 된 실행 순서 : 어린이 1

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 

최소 경우 :

귀하의 경우 (부모 2를 얻는다 두 아이들이 3 수)

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

나는 동시에 test/0을 실행 100000 개 프로세스를 양산 대규모 테스트를 작성 얻고 카운트 모든 프로세스 read(Server) resault 외부 stat_server을 만들고 여기있다했습니다 루카스의 대답을 이해하기

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

당신이 말해 줄 수 라인 B가 동일한 프로세스에서 메시지는 발생 후 발송에 실패하는 메시지를 지정에게 전달 될 것입니다 목적지 프로세스가 A? 그리고 왜이 프로세스들 각각이'read '전에'incr'을 보내는가? – user1579701

+0

@ user1579701 모든 프로세스는 read (Server) 전에 incr (Server)을 실행합니다. read/1의 정의를 보라. 스폰 기능은 새로운 프로세스 만 생성합니다. 실행이 완료되거나 함수 실행을 시작하기 전까지 기다리지 않습니다. –

+0

@ user1579701 방금 아동의 읽기 2에 대한 최소값의 경우 내 실수를 발견했습니다. 내 대답을 편집했습니다. –

2

한 정밀 모든 서버이다 인터페이스 (read, incr, reset)는 동기식입니다. 서버에서 응답을 기다립니다. 즉,이 인터페이스를 사용하는 프로세스는 서버가 요청을 완료 할 때까지 아무 것도 할 수 없습니다. 자녀 2가 2 미만을 읽을 수 없다는 것을 정당화하는 것이 매우 중요합니다.프로세스를 시각화하는

2 시퀀스 다이어그램 :

enter image description here

enter image description here

+0

그래서'incr (Server)'가 확인 응답을 기다리지 않고 메시지를 보내는 경우 자식 2도 1을 읽을 수 있습니까? 나는 코드를 수정하여 (기회를 증가시키기 위해 삭제 된 자식 1을 삭제) 수백만 개의 프로세스와 자식 2가 읽지 않은 수많은 대규모 테스트를 실행했다. 메시지 전달의 구현에 대한 간단한 설명은 찾을 수 없지만 소스 코드에 대한 이해는 찾지 못했다. (가난한 정말로) 메시지 전달 및 메시지 큐, 자식 2 어쨌든 1을 읽을 수 없습니다. 그러나 단지 패러다임이 아닌 구현 일뿐입니다. –

+1

서버를 실행하는 코어가 다른 것들로 바쁘면 다른 메시지가이 코어에서 모두 함께 처리되기를 기다리고있을 것입니다 (추측에 따라 다른 버전의 메시지가 어떻게 구현되는지 모르겠습니다. 빔 기계). 그런 다음 child2의 incr 및 read 메시지가 먼저 취해진 것일 수 있습니다. 최소한 그것이 결코 일어나지 않을 것이라는 보장은 없습니다. – Pascal