2012-05-09 15 views
33

Estoy tratando de entender los conceptos básicos de subprocesamiento y concurrencia. Quiero un caso simple en el que dos hilos intenten acceder repetidamente a un recurso compartido.Enhebrado de Python. ¿Cómo bloqueo un hilo?

El código:

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() 

lo tanto, tengo dos hilos, ambos tratando de incrementar el contador. Pensé que si el hilo 'A' se llamaba incre(), se establecería el lock, impidiendo que 'B' accediera hasta que se haya liberado 'A'.

Al ejecutar, deja en claro que este no es el caso. Obtienes todos los incrementos aleatorios de datos aleatorios.

¿Cómo se usa exactamente el objeto de bloqueo?

Editar, Además, he intentado poner los bloqueos dentro de las funciones de subprocesos, pero todavía no tuve suerte.

+0

Su código no se ejecuta. –

+0

@Ignacio Vazquez-Abrams - Debería ahora. Dejé fuera el bit 'if __name__'. ¿Es eso lo que usted se refería? – Zack

+1

Tampoco funciona para mí. Esperaría que tu creación de hilo se viera como 'hello = threading.Thread (target = hello_there)' y luego para que el hilo se inicie 'hello.start()'. –

Respuesta

40

Puede ver que sus bloqueos funcionan bastante mientras los está utilizando, si reduce la velocidad del proceso y los bloquea un poco más. Tuviste la idea correcta, donde rodeas pedazos críticos de código con la cerradura. Aquí hay un pequeño ajuste a su ejemplo para mostrarle cómo cada uno espera al otro para liberar el bloqueo.

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() 

Salida de ejemplo:

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

¡Oh, limpio! Supongo que me estaba confundiendo el 'conteo de copias' en' main() 'mostrando iteración errática. Pero supongo que hace que sea como si tuviera tres bucles corriendo al mismo tiempo. ¡Gracias! También TIL sobre el módulo de inspección. Muy genial. – Zack

+0

@Zack: Ya supongo que fue esa impresión principal lo que lo confundió. No tenía límite así que imprimía más rápido de lo que los hilos lo estaban cambiando. – jdi

+0

@jdi Estoy tratando de entender el bloqueo, así que agregué una impresión (conteo) a su función incremental justo después del recuento + = 1, pero cuando ejecuto el código, ¿llega a 6? – ErinGoBragh

Cuestiones relacionadas