Threading und while

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Mupx
User
Beiträge: 5
Registriert: Montag 19. April 2021, 15:54

Ich habe folgenden Code:
import threading
class meinfred(threading.Thread):
ergebnis = [0,1]

def __init__(self, name, iD):
threading.Thread.__init__(self)
self.name = name
self.iD = iD
print("Hallo")

def run(self):
i = 0
while i < 20:
lockme.acquire()
zahl = meinfred.ergebnis[len(meinfred.ergebnis) - 2] + meinfred.ergebnis[len(meinfred.ergebnis) - 1]
meinfred.ergebnis.append(zahl)
lockme.release()
i = i+1

t1 = meinfred("thread1", 1)
t2 = meinfred("thread2", 2)
t3 = meinfred("thread3", 3)

lockme = threading.Lock()

t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()

print(meinfred.ergebnis[5])

und frage mich, wieso ich das i brauche. Ich hab es ohne versucht, aber wenn ich dann bei print(meinfred.ergebnis[]) über 5 gehe kommt nur, dass das out of range ist.
Benutzeravatar
__blackjack__
User
Beiträge: 14076
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Mupx: Die Frage hat letztlich mit Threading überhaupt nichts zu tun, weil der Teil der die Liste bearbeitet ja den Zugriff durch ein Lock serialisiert. Und was heisst Du hast es ohne `i` versucht? Du hast das ``while`` weg gelassen und den Code darin dann 20 mal hingeschrieben? Denn anders kannst Du das `i` ja nicht wirklich weg lassen ohne das sich der Programmablauf verändert. Und wenn Du den Programmablauf veränderst, kommt natürlich was anderes heraus.

Bevor Du weiter darüber nachdenkst, solltest Du das aber erst mal generell ordentlich schreiben, denn das arbeitet nicht nur mit globalen Variablen, sondern auch noch mit *Threads* *und* globalen Variablen. Schlimmer und unübersichtlicher und fehleranfälliger geht's kaum. Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Wenn man das macht, dann sieht man, das `run()` auf `lockme` zugreift, was so nicht möglich sein sollte, weil das eine globale Variable sein müsste. Und das macht man nicht. So ”lustige” Namen übrigens bitte auch nicht. Das heisst `thread` und nicht `fred` und `mein` ist genau so eine überflüssige Vorsilbe wie das englische `my`. Klassennamen werden zudem Gross geschrieben. Und auch `ergebnis` ist global, was es auch nicht sein sollte. Sowohl das Lock als auch die Liste werden den Threads sauber als Argumente übergeben.

Dafür kann man `name` und `iD` weglassen, denn die werden nirgends verwendet.

Die `__init__()` und die `run()` enthalten auch nichts was hier wirklich eine Klasse rechtfertigt, weil man das auch einfacher mit einer Funktion machen kann.

Statt Namen zu nummerieren und immer dreimal das gleiche zum erstellen, starten, und auf's Ende warten zu schreiben, würde man eine Liste und Schleifen verwenden.

Statt der ``while``-Schleife würde man eine ``for``-Schleife schreiben.

Locks sollte man mit ``with`` verwenden. Wenn zwischen dem `aquire()` und dem `release()` eine Ausnahme ausgelöst wird, und der kritische Bereich aus anderen Gründen verlassen wird, ohne die Sperre wieder freizugeben, hängt das gesamte Programm.

``sequence[len(sequence) - n]`` ist die unnötig umständliche Art ``sequence[-n]`` zu schreiben.

So sieht's dann aus:

Code: Alles auswählen

#!/usr/bin/env python3
from threading import Lock, Thread


def run(lock, ergebnis):
    print("Hallo")
    for _ in range(20):
        with lock:
            ergebnis.append(ergebnis[-2] + ergebnis[-1])


def main():
    lock = Lock()
    ergebnis = [0, 1]

    threads = [
        Thread(target=run, args=[lock, ergebnis], daemon=True)
        for _ in range(3)
    ]
    for thread in threads:
        thread.start()
    for thread in threads:
        thread.join()

    print(ergebnis[5])


if __name__ == "__main__":
    main()
Und das ist ein schlechtes Beispiel für Threads weil es keinen Sinn macht, denn letztlich behindern die sich alle gegenseitig durch das Lock. Das Problem selbst ist so halt schon nicht parallelisierbar.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten