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
.

 

  1. Schreckliche Erklärungen sind das hier. Erlang hat Prozesse, keine Threads und man darf ruhig erwähnen, dass diese nichts mit den Prozesses des OS zu tun haben, den wirren Sachen hier über asynchrone Nachrichten, self() mitsenden verstehe ich nur, weil ich vorher schon kannte.