Effizienter Austausch einer Variable zwischen n Threads?

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
Applepearlol
User
Beiträge: 14
Registriert: Samstag 10. August 2013, 21:27

Hallo,

ich habe n Threads, welche alle eine Variable Teilen sollen(r/w), welche anzeigt ob der I2C Bus gerade genutzt wird(Boolean).
Bisher habe ich meine variable in einem der Threads definiert und sie den anderen jeweils beim start übergeben. Funktioniert auch ganz gut, nur gibt es da eine elegantere/effizientere Lösung?
BlackJack

@Applepearlol: Brauchst Du an der Stelle dann nicht sowieso mindestens ein Sperrobjekt (`threading.Lock`)?
Applepearlol
User
Beiträge: 14
Registriert: Samstag 10. August 2013, 21:27

@BlackJack:
stimmt, hatte ich vergessen zu erwähnen.
Die jetzige Struktur für Zugriffe sieht so aus:

Code: Alles auswählen

self.lockobj.acquire()
self.master.i2c_use = 1
self.lockobj.release()


#do things with I2C Bus


self.lockobj.acquire()
self.master.i2c_use = 0
self.lockobj.release()
BlackJack

@Applepearlol: Das `Lock` selbst ist doch schon ein Flag. Du kannst abfragen ob es gerade benutzt wird und da wird es dann immer den gleichen Wert liefern wie Dein boole'sches Falg (was Zahlen statt `True`/`False` benutzt‽). Denn eigentlich will man ja die Operation auf dem Bus absichern und nicht so ein Flag. Und da wollte man dann auch dafür sorgen das die Sperre auf jeden Fall wieder aufgehoben wird. Mit ``with``:

Code: Alles auswählen

with self.lock:
    # do things with I2C Bus
Woanders kannst Du mit ``if i2c_using_object.lock.locked():`` abfragen ob der Bus gerade benutzt wird.

Der Namenszusatz `obj` bei `lockobj` ist überflüssig denn in Python ist alles was man an einen Namen binden kann ein Objekt. Das muss man deshalb nicht in jeden Namen reinschreiben. ;-)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Python kennt Booleans mit `True` und `False`.
Und je nachdem wie deine Zugriffsmuster aussehen kannst du doch direkt das Lock benutzen, um die I2C benutzung zu regeln. Bekommt der Thread das Lock, dann darf er auch schreiben.
Dann ist das ganze auch Threadsicher, anders als momentan.
Daneben benutzt `threading.Lock` das Contextmanager Protokoll.

Zusammen:

Code: Alles auswählen

with self.lockobj:
    #do things with I2C Bus
Edit: Natuerlich war Blackjack schneller :roll: Na vielleicht hat er ja was vergessen :D
Applepearlol
User
Beiträge: 14
Registriert: Samstag 10. August 2013, 21:27

Also würde ich dann schreiben

Code: Alles auswählen

with self.lock.acquire():
	do something

oder

Code: Alles auswählen

with self.lock:
	do something
Woher weiß with denn welche Methode aufgerufen werden soll, wenn es wieder aus dem with statement rausgeht? hier wäre das nämlich self.lock.release()
BlackJack

@Applepearlol: Es muss ``with self.lock:`` heissen. Beim verlassen des ``with``-Blocks wird immer die `__exit__()`-Methode aufgerufen. Und am Anfang immer die `__enter__()`-Methode. Die müssen dann das entsprechende tun, also beispielsweise bei Sperren `aquire()` und `release()`, bei Dateien nichts und `close()`, und so weiter. Dafür ist das jeweilige Objekt selbst zuständig.
Antworten