2012-05-09 11 views
33

Ich versuche, die Grundlagen von Threading und Parallelität zu verstehen. Ich möchte einen einfachen Fall, in dem zwei Threads wiederholt versuchen, auf eine freigegebene Ressource zuzugreifen.Python-Threading. Wie sperre ich einen Thread?

Der Code:

import threading 

class Thread(threading.Thread): 
    def __init__(self, t, *args): 
     threading.Thread.__init__(self, target=t, args=args) 
     self.start() 
count = 0 
lock = threading.Lock() 

def incre(): 
    global count 
    lock.acquire() 
    try: 
     count += 1  
    finally: 
     lock.release() 

def bye(): 
    while True: 
     incre() 

def hello_there(): 
    while True: 
     incre() 

def main():  
    hello = Thread(hello_there) 
    goodbye = Thread(bye) 

    while True: 
     print count 

if __name__ == '__main__': 
    main() 

Also, ich habe zwei Threads, die beide versuchen, den Zähler zu erhöhen. Ich dachte, dass, wenn der Thread "A" incre() heißt, die lock eingerichtet würde, wodurch verhindert wird, dass "B" zugreift, bis "A" freigegeben wurde.

Das Ausführen der macht es klar, dass dies nicht der Fall ist. Sie erhalten alle zufälligen Daten race-ish Inkrementen.

Wie genau wird das Sperrobjekt verwendet?

Edit, Zusätzlich habe ich versucht, die Sperren innerhalb der Thread-Funktionen, aber immer noch kein Glück.

+0

Ihr Code nicht ausgeführt. –

+0

@Ignacio Vazquez-Abrams - Sollte jetzt. Ich habe das 'if __name__' Bit weggelassen. Hast du damit gemeint? – Zack

+1

Es läuft auch nicht für mich. Ich würde erwarten, dass Ihre Thread-Erstellung wie folgt aussehen würde: 'hallo = threading.Thread (target = hallo_there)' und dann, damit der Thread 'hello.start()' gestartet wird. –

Antwort

40

Sie können sehen, dass Ihre Sperren so gut funktionieren, wie Sie sie verwenden, wenn Sie den Prozess verlangsamen und sie ein wenig mehr blockieren lassen. Sie hatten die richtige Idee, wo Sie mit dem Schloss kritische Code-Teile umgeben. Hier ist eine kleine Anpassung an Ihr Beispiel, um Ihnen zu zeigen, wie jeder auf die andere wartet, um die Sperre aufzuheben.

import threading 
import time 
import inspect 

class Thread(threading.Thread): 
    def __init__(self, t, *args): 
     threading.Thread.__init__(self, target=t, args=args) 
     self.start() 

count = 0 
lock = threading.Lock() 

def incre(): 
    global count 
    caller = inspect.getouterframes(inspect.currentframe())[1][3] 
    print "Inside %s()" % caller 
    print "Acquiring lock" 
    with lock: 
     print "Lock Acquired" 
     count += 1 
     time.sleep(2) 

def bye(): 
    while count < 5: 
     incre() 

def hello_there(): 
    while count < 5: 
     incre() 

def main():  
    hello = Thread(hello_there) 
    goodbye = Thread(bye) 


if __name__ == '__main__': 
    main() 

Beispielausgabe:

... 
Inside hello_there() 
Acquiring lock 
Lock Acquired 
Inside bye() 
Acquiring lock 
Lock Acquired 
... 
+0

Oh, ordentlich! Ich glaube, ich wurde durch die 'print count' in' main() 'verwirrt, die unregelmäßige Iterationen zeigten. Aber ich denke, es ist irgendwie so, dass ich drei Schleifen gleichzeitig laufen lasse. Vielen Dank! Auch TIL über das Inspektionsmodul. Sehr cool. – Zack

+0

@Zack: Ya Ich nehme an, es war der Hauptdruck, der dich verwirrte. Es hatte keine Grenzen, also druckte es schneller, als die Fäden es veränderten. – jdi

+0

@jdi Ich versuche, Sperren zu verstehen, also habe ich einen Ausdruck (Anzahl) zu Ihrer Inkr-Funktion direkt nach der Zählung + = 1 hinzugefügt, aber wenn ich den Code ausführen, wird es zu 6? – ErinGoBragh

Verwandte Themen