English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Concordanza Erlang

La programmazione concorrente in Erlang deve seguire i seguenti principi di base o procedure.

La lista include i seguenti principi:

piD = spawn(Fun)

Creare un nuovo processo connesso a valutare Fun. Il nuovo processo esegue in parallelo con il chiamante. Un esempio è il seguente-

Esempio

-module(helloworld). 
-export([start/0]). 
start() ->
   spawn(fun() -> server("Ciao") end). 
server(Messaggio) ->
   io:fwrite("~p",[Messaggio]).

L'output del programma sopra è -

Output

"Ciao"

Pid ! Messaggio

Inviare messaggi al processo utilizzando l'identificatore Pid. L'invio dei messaggi è asincrono. Il mittente non aspetta, ma continua a fare ciò che sta facendo. Il "!" è chiamato operatore di invio.

Un esempio di esempio-

Esempio

-module(helloworld). 
-export([start/0]). 
start() -> 
   Pid = spawn(fun() -> server("Ciao") end), 
   Pid ! {ciao}. 
server(Messaggio) ->
   io:fwrite("~p",[Messaggio]).

Ricevere…fine

Ricevere i messaggi già inviati al processo. Ha la seguente sintassi-

Sintassi

ricezione
Pattern1 [quando Guard1] ->
Expressions1;
Pattern2 [quando Guard2] ->
Espressioni2;
...
Fine

Quando il messaggio raggiunge questo processo, il sistema tenta di abbinarlo a Pattern1 (potrebbe esserci un Guard 1). Se ha successo, valuta le Expressions1. Se il primo modello non corrisponde, tenta di utilizzare Pattern2, e così via. Se nessun modello corrisponde, il messaggio viene salvato per la gestione futura e il processo attende il messaggio successivo.

Il seguente programma mostra un esempio dell'intero processo che utilizza tutti e tre i comandi.

Esempio

-module(helloworld). 
-export([loop/0, start/0]). 
loop() ->
   ricezione 
      {rectangle, Width, Ht} -> 
         io:fwrite("L'area del rettangolo è ~p~n", [Width * Ht]), 
         loop(); 
      {circle, R} ->
      io:fwrite("L'area del cerchio è ~p~n", [3.14159 * R * R]), 
      loop(); 
   Other ->
      io:fwrite("Unknown"), 
      loop() 
   fine. 
start() ->
   Pid = spawn(fun() -> loop() end), 
   Pid ! {rectangle, 6, 10}.

Riguardo al programma sopra, è necessario notare i seguenti punti:

  • La funzione loop ha un ciclo di ricezione. Pertanto, quando un messaggio viene inviato, viene elaborato dal ciclo di ricezione.

  • Generare un nuovo processo che passerà alla funzione loop.

  • Inviare un messaggio al processo generato utilizzando il comando Pid! message.

L'output del programma sopra è -

Output

L'area del rettangolo è 60

Numero massimo di processi

Concurrentemente, è importante determinare il numero massimo di processi permessi sul sistema. Poi, dovresti essere in grado di capire quanti processi possono essere eseguiti contemporaneamente sul sistema.

Lasciate che vi mostriamo un esempio di come determinare il numero massimo di processi eseguibili sul sistema.

-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("Tempo spawn processo=~p (~p) microsecondi~n", [U1, U2]).
   attendere() -> 
   
   ricezione 
      morire -> void 
   fine. 
 
for(N, N, F) -> [F()]; 
for(I, N, F) -> [F()|for(I+1, N, F)]. 
start()->
   max(1000), 
   max(100000).

Sui computer con buona capacità di elaborazione, entrambe le funzioni massime menzionate sopra passano. Di seguito è riportato un esempio di output del programma sopra menzionato.

Massimo numero di processi consentiti:262144
Tempo spawn processo=47.0 (16.0) microsecondi
Massimo numero di processi consentiti:262144
Processo spawn tempo=12.81 (10.15) microsecondi

Ricezione con timeout

A volte, la frase di ricezione potrebbe aspettare per sempre un messaggio che non apparirà mai. Questo potrebbe avere molte ragioni. Ad esempio, potrebbe esserci un errore logico nel nostro programma, o il processo che deve inviarci un messaggio potrebbe essere crollato prima di inviare il messaggio. Per evitare questo problema, possiamo aggiungere un timeout alla frase di ricezione. Questo imposterà il tempo massimo che il processo può aspettare per ricevere un messaggio.

Di seguito è riportata la sintassi della ricezione di messaggi con timeout specificato

Sintassi

ricezione 
Pattern1 [quando Guard1] -> 
Expressions1; 
Pattern2 [quando Guard2] ->
Espressioni2; 
... 
dopo Tempo -> 
Espressioni 
fine

Il caso più semplice è creare una funzione sleeper, come mostrato nel programma di seguito.

Esempio

-module(helloworld). 
-export([sleep/1,start/0]). 
sleep(T) ->
   ricezione 
   dopo T -> 
      true 
   fine. 
   
start()->
   sleep(1000).

Il codice sopra menzionato si addormenterà per 1000 millisecondi prima di uscire effettivamente.

Ricezione selettiva

Ogni processo in Erlang ha una posta associata. Quando si invia un messaggio a questo processo, il messaggio viene messo nella posta. Il controllo di questa posta avviene solo quando il programma valuta la frase di ricezione.

Di seguito è riportata la sintassi generale della frase di ricezione selettiva.

Sintassi

ricezione 
Pattern1 [quando Guard1] ->
Expressions1; 
Pattern2 [quando Guard1] ->
Expressions1; 
... 
dopo 
Tempo ->
ExpressionTimeout 
fine

Questo è il modo in cui funziona la frase di ricezione sopra menzionata-

  • Quando inseriamo una dichiarazione receive, avviamo un timer (ma solo se l'espressione contiene un'unità after).

  • Prendere la prima mail nel mailbox e tentare di corrispondere con Pattern1, Pattern2 ecc. Se la corrispondenza è riuscita, la mail viene rimossa dal mailbox e valutata l'espressione dopo il modello.

  • Se nessun modello nella dichiarazione receive corrisponde alla prima mail nel mailbox, la prima mail viene rimossa dal mailbox e messa nella "coda di conservazione". Poi provare con la seconda mail nel mailbox. Ripetere questo processo fino a trovare una corrispondenza o aver controllato tutte le mail nel mailbox.

  • Se tutte le mail nel mailbox non corrispondono, il processo viene sospeso e riagganciato al prossimo messaggio nuovo inserito nel mailbox. Notare che quando si riceve un nuovo messaggio, le mail nella coda di conservazione non vengono riacquisite; solo il nuovo messaggio viene corrisposto.

  • Una volta corrisposto un messaggio, tutte le mail inserite nella coda di conservazione vengono reimpostate nell'ordine di arrivo nel mailbox. Se è stato impostato un timer, annullarlo.

  • Se il timer è scaduto mentre si aspettava un messaggio, valutare l'espressione ExpressionsTimeout e riporre tutte le mail salvate nell'ordine di arrivo nel mailbox.