Erlang-동시성

Erlang의 동시 프로그래밍에는 다음과 같은 기본 원칙 또는 프로세스가 있어야합니다.

목록에는 다음 원칙이 포함됩니다.

piD = spawn (재미 있음)

Fun을 평가하는 새로운 동시 프로세스를 만듭니다. 새 프로세스는 호출자와 병렬로 실행됩니다. 예는 다음과 같습니다-

-module(helloworld). 
-export([start/0]). 

start() ->
   spawn(fun() -> server("Hello") end). 

server(Message) ->
   io:fwrite("~p",[Message]).

위 프로그램의 출력은 다음과 같습니다.

산출

“Hello”

Pid! 메시지

식별자 Pid를 사용하여 프로세스에 메시지를 보냅니다. 메시지 전송은 비동기식입니다. 발신자는 기다리지 않고하던 일을 계속합니다.‘!’ 송신 연산자라고합니다.

예는 다음과 같습니다-

-module(helloworld). 
-export([start/0]). 
start() -> 
   Pid = spawn(fun() -> server("Hello") end), 
   Pid ! {hello}. 

server(Message) ->
   io:fwrite("~p",[Message]).

받기… 끝

프로세스로 전송 된 메시지를 수신합니다. 다음과 같은 구문이 있습니다.

통사론

receive
Pattern1 [when Guard1] ->
Expressions1;
Pattern2 [when Guard2] ->
Expressions2;
...
End

메시지가 프로세스에 도착하면 시스템은이를 Pattern1 (보호 Guard1 사용 가능)과 일치 시키려고합니다. 이것이 성공하면 Expressions1을 평가합니다. 첫 번째 패턴이 일치하지 않으면 Pattern2를 시도합니다. 일치하는 패턴이 없으면 나중에 처리 할 수 ​​있도록 메시지가 저장되고 프로세스는 다음 메시지를 기다립니다.

다음 프로그램에는 3 개의 명령이 모두 포함 된 전체 프로세스의 예가 나와 있습니다.

-module(helloworld). 
-export([loop/0,start/0]). 

loop() ->
   receive 
      {rectangle, Width, Ht} -> 
         io:fwrite("Area of rectangle is ~p~n" ,[Width * Ht]), 
         loop(); 
      {circle, R} ->
      io:fwrite("Area of circle is ~p~n" , [3.14159 * R * R]), 
      loop(); 
   Other ->
      io:fwrite("Unknown"), 
      loop() 
   end. 

start() ->
   Pid = spawn(fun() -> loop() end), 
   Pid ! {rectangle, 6, 10}.

위 프로그램에 대해 다음 사항에 유의해야합니다.

  • 루프 기능에는 수신 종료 루프가 있습니다. 따라서 메시지가 전송되면 수신 종료 루프에 의해 처리됩니다.

  • 루프 기능으로 이동하는 새로운 프로세스가 생성됩니다.

  • 메시지는 Pid를 통해 생성 된 프로세스로 전송됩니다. 메시지 명령.

위 프로그램의 출력은 다음과 같습니다.

산출

Area of the Rectangle is 60

최대 프로세스 수

동시성에서는 시스템에서 허용되는 최대 프로세스 수를 결정하는 것이 중요합니다. 그러면 시스템에서 동시에 실행할 수있는 프로세스 수를 이해할 수 있어야합니다.

시스템에서 실행할 수있는 최대 프로세스 수를 결정하는 방법의 예를 살펴 보겠습니다.

-module(helloworld). 
-export([max/1,start/0]). 

max(N) -> 
   Max = erlang:system_info(process_limit), 
   io:format("Maximum allowed processes:~p~n" ,[Max]), 
   
   statistics(runtime), 
   statistics(wall_clock), 
   
   L = for(1, N, fun() -> spawn(fun() -> wait() end) end), 
   {_, Time1} = statistics(runtime), 
   {_, Time2} = statistics(wall_clock), lists:foreach(fun(Pid) -> Pid ! die end, L), 
   
   U1 = Time1 * 1000 / N, 
   U2 = Time2 * 1000 / N, 
   io:format("Process spawn time=~p (~p) microseconds~n" , [U1, U2]).
   wait() -> 
   
   receive 
      die -> void 
   end. 
 
for(N, N, F) -> [F()]; 
for(I, N, F) -> [F()|for(I+1, N, F)]. 

start()->
   max(1000), 
   max(100000).

처리 능력이 좋은 컴퓨터에서는 위의 최대 기능이 모두 통과됩니다. 다음은 위 프로그램의 샘플 출력입니다.

Maximum allowed processes:262144
Process spawn time=47.0 (16.0) microseconds
Maximum allowed processes:262144
Process spawn time=12.81 (10.15) microseconds

시간 초과로 받기

때때로 receive 문은 오지 않는 메시지를 영원히 기다릴 수 있습니다. 여러 가지 이유가있을 수 있습니다. 예를 들어, 프로그램에 논리적 오류가 있거나 메시지를 보내려는 프로세스가 메시지를 보내기 전에 충돌했을 수 있습니다. 이 문제를 방지하기 위해 receive 문에 제한 시간을 추가 할 수 있습니다. 프로세스가 메시지 수신을 대기하는 최대 시간을 설정합니다.

다음은 제한 시간이 지정된 수신 메시지의 구문입니다.

통사론

receive 
Pattern1 [when Guard1] -> 
Expressions1; 

Pattern2 [when Guard2] ->
Expressions2; 
... 
after Time -> 
Expressions 
end

가장 간단한 예는 다음 프로그램과 같이 sleeper 함수를 만드는 것입니다.

-module(helloworld). 
-export([sleep/1,start/0]). 

sleep(T) ->
   receive 
   after T -> 
      true 
   end. 
   
start()->
   sleep(1000).

위의 코드는 실제로 종료되기 전에 1000Ms 동안 휴면합니다.

선택적 수신

Erlang의 각 프로세스에는 연결된 사서함이 있습니다. 프로세스에 메시지를 보내면 메시지가 사서함에 저장됩니다. 이 메일 함이 검사되는 유일한 시간은 프로그램이 수신 명령문을 평가할 때입니다.

다음은 선택적 수신 문의 일반 구문입니다.

통사론

receive 
Pattern1 [when Guard1] ->
Expressions1; 

Pattern2 [when Guard1] ->
Expressions1; 
... 
after 
Time ->
ExpressionTimeout 
end

이것은 위의 수신 문이 작동하는 방법입니다-

  • receive 문을 입력하면 타이머가 시작됩니다 (그러나 표현식에 after 섹션이있는 경우에만 해당).

  • 사서함의 첫 번째 메시지를 가져 와서 Pattern1, Pattern2 등과 일치 시키십시오. 일치가 성공하면 메일 함에서 메시지가 제거되고 패턴 다음의 표현식이 평가됩니다.

  • receive 문의 패턴이 메일 함의 첫 번째 메시지와 일치하지 않으면 첫 번째 메시지가 메일 함에서 제거되고 "저장 대기열"에 배치됩니다. 그런 다음 사서함의 두 번째 메시지가 시도됩니다. 이 절차는 일치하는 메시지를 찾거나 사서함의 모든 메시지를 검사 할 때까지 반복됩니다.

  • 사서함의 메시지 중 일치하는 메시지가 없으면 프로세스가 일시 중단되고 다음에 새 메시지가 사서함에 들어갈 때 실행을 위해 다시 예약됩니다. 새 메시지가 도착하면 저장 대기열의 메시지가 다시 일치하지 않습니다. 새 메시지 만 일치합니다.

  • 메시지가 일치하는 즉시 저장 큐에 넣은 모든 메시지는 프로세스에 도착한 순서대로 메일함에 다시 입력됩니다. 타이머가 설정되어 있으면 지워집니다.

  • 메시지를 기다리는 동안 타이머가 경과하면 ExpressionsTimeout 표현식을 평가하고 저장된 메시지를 프로세스에 도착한 순서대로 사서함에 다시 넣습니다.