Kategorien
Erlang

Threads in Erlang

Mit Erlang lässt sich besonders einfach verteilter Code schreiben, der auf verschiedenen Threads Laufen kann ohne Probleme.

Erlang ist somit die Sprache der Wahl um verteilte Anwendungen zu schreiben.

Regeln bei Threads in Erlang

  • Threads greifen dabei nicht auf gemeinsamen Speicherraum zu, sondern kommunizieren nur über Messages miteinander, um Kollisionen auszuschließen.
  • Senden ist asynchron, für synchrone Nachrichten muss self() mitgesendet und ausgewertet werden (self gibt die eigene Pid aus)
  • zum Kommunizieren zwischen den Prozessen kann entweder die Pid mitgesendet werden (elegant), oder erfragt werden mit whereis()

Anbei ein kleines Beispiel bei dem die 3 verschiedenen Threads Berechnungen durchführen und sich die Ergebnisse untereinander zuschicken.

Das Programm soll eine Implementierung sein von Modulo 3, also ein Test, ob eine ganze Zahl durch3 teilbar ist, funktioniert leider nur nicht, aber die Threads kommunizieren erfolgreich miteinander, was man auf der Konsole sehen kann  🙂

Beispielaufruf der Funktion:

threadBsp(15).
threadBsp(Zahl)->

%Prozesse beenden, vom letzten Start, sonst Absturz, wenn vorher nicht beendet
killProcessWhenStarted(p1),
killProcessWhenStarted(p2),
killProcessWhenStarted(p3),

%Prozesse starten
Pid1 = spawn(p1()),
io:format("P1 gestartet mit Pid: ~w \n",[Pid1]),
register(p1, Pid1),

Pid2 = spawn(p2()),
io:format("P2 gestartet mit Pid: ~w \n",[Pid2]),
register(p2, Pid2),

Pid3 = spawn(p3()),
io:format("P3 gestartet mit Pid: ~w \n",[Pid3]),
register(p3, Pid3),

io:format("Prozesse gestartet, Berechnugn beginnt \n")
Pid1!{"Start", Zahl},

%ListPids = registered(),
%io:format("Registrierte Prozesse: ~w \n",[ListPids])
.

p1()->fun()->
    receive        
    {From, "end" } -> exit(self(), kill);
    {From,Zahl} ->
        io:fwrite("P1 hat Wert ~w bekommen \n",[Zahl]),
        Rest = Zahl rem 2,
        ErgebnisRund = Zahl div 2,
        if ErgebnisRund == 0 ->
                if Rest == 0 ->
                    io:fwrite("durch 3 teilbar! \n",[]);
                true ->
                    io:fwrite("nicht durch 3 teilbar! \n",[])
                end;
            true  ->
                if Rest == 0 ->
                    self()!{self(), ErgebnisRund};
                   true  ->
                       P2 = whereis(p2),
                       P2!{self(), ErgebnisRund}
                end,
                %continue running
                Loop = p1(),
                Loop()
        end
    end
end.

p2()->fun()->
    receive
        {From, "end" } -> exit(self(), kill);
        {From, Zahl} ->
            io:fwrite("P2 hat Wert ~w bekommen \n",[Zahl]),
            Rest = Zahl rem 2,
            ErgebnisRund = Zahl div 2,
            if ErgebnisRund == 0 ->
                    io:fwrite("nicht durch 3 teilbar! \n",[]);
                true  ->             
                if Rest == 0 ->
                       P3 = whereis(p3),
                       P3!{self(), ErgebnisRund};            
                   true  ->
                       From!{self(), ErgebnisRund}
                end,
                %continue running
                Loop = p2(),
                Loop()
            end
    end
end.

p3()->fun()->
    receive
        {From, "end" } -> exit(self(), kill);
        {From, Zahl} ->         
            io:fwrite("P3 hat Wert ~w bekommen \n",[Zahl]),
            Rest = Zahl rem 2,
            ErgebnisRund = Zahl div 2,
            if ErgebnisRund == 0 ->
                    io:fwrite("nicht durch 3 teilbar! \n",[]);
                true  ->             
                if Rest == 1 ->
                        From!{self(), ErgebnisRund};                           
                   true  ->
                        From!{self(), ErgebnisRund}
                end,
                %continue running
                Loop = p3(),
                Loop()
            end
    end
end.

killProcessWhenStarted(Name)->
    Pid = whereis(Name),
    if Pid /= undefined -> exit(Pid, kill);
       true  -> io:format("Prozesse beendet ~w \n", [Name])
    end
.