Variablenänderung atomic ?

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
jasonts
User
Beiträge: 5
Registriert: Freitag 25. Februar 2011, 05:18

Hi,
ich arbeite zur Zeit mit Threads und möchte eine Referenz zu Variablen übergeben. Aus diesen Variablen werden Einstellungen gelesen. Ein extra Thread ist dafür verantwortlich die Einstellungen regelmäßig aus einer Datenbank zu holen und die Variablen ggf. zu aktualisieren.

Muss ich die Variable mit den Einstellungen über einen lock-Mechanismus schützen oder ist das Ändern von Variablen (z.B. append / überschreiben von listenelementen) atomic ? Mir ist egal ob der Thread vor oder nach der Änderung auf die Einstellungsvariable zugreift. Ich möchte nur Fehler vermeiden bei denen die Variable zwischenzeitlich nicht verfügbar ist.

Gibt es generell eine Liste die mir sagt was atomic / thread-safe ist und was nicht ?

Grüße,
Micha
problembär

Versuch's lieber ohne Threads.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Du verändert Datenstrukturen, dass hat nichts mit Variablen zu tun und nein die sind nicht threadsafe, du müsstest also den Zugriff mit Locks einschränken.
jasonts
User
Beiträge: 5
Registriert: Freitag 25. Februar 2011, 05:18

ich will das nochmal mit einem beispiel aufgreifen, da ich mit den antworten nicht ganz glücklich bin.

im folgenden code wird die variable self.a vom thread als "option" verwendet. diese wird zur laufzeit des threads verändert und beeinflusst ihn. für mich ist nicht wichtig, ob er kurz vor oder nach der änderung zu greift. die frage ist: besteht die möglichkeit, dass die änderung zeitgleich mit dem zugriff statt findet und so zu einem absturz führen kann ?

im beispiel ist die chance sicher gering, aber ich habe etwas ähnliches in einem einem server der sicher über lange zeit arbeiten muss, da könnten solche "zusammenstöße" dann auftreten. oder ist das zuweisen atomic und ich muss mir keine sorgen machen ?


beispiel:

Code: Alles auswählen

"""
cookies !!
"""

import threading, time


def main():
  testObj = testThread()
  testObj.start()
  time.sleep(6)
  testObj.a = "hallo peter"
  time.sleep(100)

class testThread(threading.Thread):
  def __init__(self):
    threading.Thread.__init__(self)
    self.a = "hallo welt!"
  def run(self):
    while 1:
      time.sleep(1)
      print(self.a)


if __name__ == "__main__":
  main()
Zuletzt geändert von Anonymous am Dienstag 20. September 2011, 06:56, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@jasonts: So ein Attributzugriff ist threadsicher. Wobei man allerdings im Hinterkopf behalten sollte, dass der Punktoperator auch hinter den Kulissen zu einem beliebigen Funktionsaufruf führen kann — Stichwort `property()`. Also nicht jede ``o.a``/``o.a = v``-Kombination muss threadsicher sein.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mag sein, dass ich in der Spezifikation etwas verpasst habe, aber wo ist definiert, dass ein Attributzugriff threadsicher sein muss? Bei CPython ist diese Eigenschaft offensichtlich, bei anderen Implementierungen sehe ich das nicht unbedingt.
Das Leben ist wie ein Tennisball.
deets

Es gibt keine Spezifikation fuer Python. Darum kann man das auch nicht nachschlagen. Jetzt kann man natuerlich ganz rauf auf's hohe Ross sich werfen und sagen "was nicht definiert ist, darf nicht benutzt werden". Aber das faende ich etwas uebertrieben. Schliesslich haben wir die Nachteile des GIL in CPython auch zu tragen - da kann man dann wenigstens die Vorteile geniessen...
lunar

@deets: CPython ist nicht die einzige Python-Implementierung, und andere Implementierungen haben nicht zwingend einen GIL. Die Frage nach der Spezifikation ist mithin nicht übertrieben, zumal EyDu sich auch explizit auf „andere Implementierungen“ bezogen hat. Und es soll ja wirklich Leute geben, die tatsächlich pypy oder sogar jython nutzen… ;)
jasonts
User
Beiträge: 5
Registriert: Freitag 25. Februar 2011, 05:18

also ich benutze im moment das das einfache python 2.6. wenn ich jetzt ein threading.Lock sperre, bevor ich an der variable etwas ändere oder auslese, bin ich dann auf der sicheren seite ? oder ist das komplett überflüssig ? das lock wäre allerdings immernoch ein attribut in einem objekt.
deets

@jasonts

Natuerlich ist das lock auch ein Attribut, aber das wird ja in einer nicht-konkurrierenden Situation einmal erzeugt und danach nur gelesen. Kann also nie Probleme machen.

Wenn du CPython benutzt, dann kannst du dich darauf verlassen, dass Operationen wie Attributzugriff und Veraenderungen von zB collections nicht zum Absturz fuehren. Wobei natuerlich zwei Threads + eine Collection durchaus race-conditions erzeugen koennen, und die koennen auch dein Programm abschmieren lassen - aber nicht mit nem segfault, sondern dann halt zB nen Index-Error beim Zugriff auf eine Liste.

Ganz konkret fuer deinen Anwendungsfall: es ist kein Problem, aus einem Thread Attribute zu setzen, und die in anderen lesend zu benutzen.
BlackJack

@EyDu: Definiert ist das nirgends aber die gängigen Python-Implementierungen halten sich daran. Schon alleine aus der praktischen Erwägung weil sich existierender Python-Quelltext darauf verlässt, dass dabei zumindest der Interpreter selbst nicht in einen inkonsistenten Zustand gerät. Der Artikel We need Software Transactional Memory auf dem PyPy-Blog schneidet das Thema auch ein wenig an.
Antworten