threadsafety

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
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Weiss jemand, ob die boolsche Auswertung eines Dictionaries threadsafe / im GIL-Sinne atomar ist?

Bsp:

Code: Alles auswählen

d = {}

# 1. Thread
if d: # mit oder ohne Lock?
    # usw.

# 2. Thread
with lock:
    d[x] = y # alteriert d
In der Doku steht zwar, dass das prinzipiell threadsafe sein sollte, allerdings möchte ich mich nicht auf irgendwelche GIL-Spezereien einlassen und tendiere eher dazu, einen Lock zuviel zu setzen. Wie seht ihr das?
deets

Also so wie dargestellt bringt's nix. Denn nur ein Thread, der ein Lock benutzt - dann hast du nix davon. Und jetzt haengt es von der ersten if-anweisung ab: wenn das was darin passiert wieder mit d arbeitet - dann solltest du locken. Denn dann kann der 2te thread eine Aenderung machen, die genau diese Bedingung verletzt.

Als Faustregel halte ich mich an das hier: wenn ein Thread nur produziert, und der andere nur konsumiert, dann braucht man keine locks. Denn dann baut zB der eine Thread neue Werte ein, und der andere entfernt sie.

In dem Moment, wo der Produzent zB statt neuen Keys mit Werten bestehende Keys mit Werten updated ist Vorsicht geboten. Dann besser locken.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Danke deets, das beantwortet meine Frage indirekt.

Zu
deets hat geschrieben:Also so wie dargestellt bringt's nix. Denn nur ein Thread, der ein Lock benutzt - dann hast du nix davon. ...
Das ist klar und Schlusselfehler in der Problembeschreibung, den 2. Thread gibts mehrfach.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Der GIL ist ein Implementationsdetail von CPython, keine Spracheigenschaft von Python. Somit solltest du immer kritische Bereiche absichern. Es ist zudem unwichtig, ob "bool(d)" nun atomar ist oder nicht, denn die Entscheidung, die darauf folgt, ist es nicht und während das "if" stattfindet, kann ein anderer Thread natürlich bereits das Dictionary verändert haben.

Stefan
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Warum ich das frage - anders als in C/C++ (und auch dort nur mit Einschränkungen) sind mir unter Python die Dinge, die am Threadstack oder Prozess-Speicher passieren, größtenteils unklar. Ohne saubere Dokumentation über threadsafe/nicht threadsafe wird es mitunter schwierig, kritische Bereiche von nicht kritischen zu trennen.

Mir ging es im obigen Bsp. tatsächlich um die boolsche Auswertung eines dictionaries, also losgelöst von Folgebetrachtungen. Wobei dieses Bsp. durch andere "primitive" Operationen zu ersetzen wäre, wo die Behandlung z.T. auch unklar ist. Leider kann man das aber ohne Betrachtung des GIL nicht aus der Sprache heraus entscheiden, für obiges Bsp. hilft der opcode, der das Schnipsel als threadsafe durch den GIL markiert. (Oder ein entsprechender Hinweis in der Dokumentation, die aber weitestgehend dort fehlen, wo man sie suchen würde - an der Objekt-, Methoden- oder Operatorenbeschreibung.)

Und gerade am simplen Ein-Producer/Ein-Comsumer-Modells wird klar, dass das mit nicht threadsafen "produce"/"consume" Operationen am Datenobjekt kritisch werden kann.

Daher die Frage, lockt ihr eher konservativ oder mit Wissen um den GIL? Oder anders, wonach schätzt ihr kritisch vs. nicht kritisch ab? Bei mir ist das gerade ein Mischmasch aus Dokumentationshinweis, opcode-Test (mit Wissen um GIL) und im Zweifelsfalle der Lock. Ohne GIL müßte ich z.T. deutlich mehr locken (es sei denn, eine alternative Impl. würde die Threadsicherheit von xy anderweitig sicherstellen), besonders schön ist das so nicht, da ich an einem Implementationsdetail hänge. Also doch mehr Locks?
BlackJack

@jerch: Aus Python-Sicht atomare Operationen sind auch threadsicher implementiert. Du kannst davon ausgehen, dass eine Python-Implementierung ob nun mit oder ohne GIL die internen Datenstrukturen schützt, sonst könnte man doch gar keine Multithreaded-Programme schreiben ohne so ziemlich *alles* in einen Lock zu setzen. Und Du solltest auch davon ausgehen können, dass alternative Implementierungen sehr penibel selber „locken” wenn sie kein GIL haben, denn sonst würde kaum ein multithreaded Programm laufen, dass unter CPython entwickelt wurde. Wenn Du mit einem Thread die internen Datenstrukturen von Python korrumpieren kannst, dann würde ich das als Fehler in der Python-Implementierung sehen.
Antworten