2012-06-19 12 views
5

Tengo diferentes hilos y después del procesamiento ponen los datos en una lista común. ¿Hay algo creado en Python para acceder a una lista o matriz numpy con un solo hilo? En segundo lugar, si no es lo que es una manera elegante de hacerlo?¿Cómo sincronizar las listas de Python?

Respuesta

4

threading proporciona Lock objetos si necesita proteger una sección crítica completa, o el módulo Queue proporciona una cola que es segura para la rosca.

4

De acuerdo con Thread synchronisation mechanisms in Python, la lectura de un solo elemento de una lista y la modificación de una lista en el lugar están garantizados para ser atómicos. Si esto es correcto (aunque parece estar en contradicción en parte por la existencia misma del módulo de cola), entonces si su código es todo de la forma:

try: 
    val = mylist.pop() 
except IndexError: 
    # wait for a while or exit 
else: 
    # process val 

Y todo poner en mylist se realiza por .append(), a continuación, su código ya es seguro para los hilos Si no confía en ese único documento en ese puntaje, use un queue.queue, que hace toda la sincronización por usted, y tiene una API mejor que list para programas concurrentes, en particular, le ofrece la opción de bloquear indefinidamente, o por un tiempo de espera , esperando .pop() para que funcionen si no tienes nada más con lo que el hilo podría estar trabajando mientras tanto.

Para las matrices numpy, y en general cualquier caso en que se necesita más que una cola de productor/consumidor, utilice un Lock o RLock de threading - estos implementan el protocolo gestor de contexto, por lo que su uso es bastante simple:

with mylock: 
    # Process as necessarry 

Y python garantizará que la cerradura se libere una vez que caiga del final del bloque with, incluso en casos complicados como si algo que usted hace genera una excepción.

Por último, considere si multiprocessing es una mejor opción para su aplicación que threading - no se garantiza que los subprocesos en Python se ejecuten realmente al mismo tiempo, y en CPython solo si el código desciende a C-level. multiprocessing soluciona este problema, pero puede tener un costo extra adicional; si no lo ha hecho aún, debe leer los documentos para determinar cuál satisface mejor sus necesidades.

+0

es un 'mylist.pop (0)' también atmoic? – willsteel

+0

Gracias por el recordatorio 'with mylock:'. Los RLocks de Imho utilizados de esa manera son a menudo la expresión más clara para proteger secciones críticas en la programación orientada a objetos. – jjmontes

+0

@willsteel para una respuesta definitiva, recomendaría mirar el código fuente de Python para ver cómo se implementan las listas, pero me gustaría * imaginar * que 'mylist.pop (0)' sería atómico si 'mylist.pop()' es (que tampoco puedo responder de manera definitiva, por lo que también menciono otros métodos de sincronización, también puede cambiar en las implementaciones de Python). En particular, todo el código de nivel C en CPython * puede * estar protegido por GIL (pero tiene la opción de liberarlo). 'pop' (probablemente) libera el GIL o no, independientemente de su argumento. – lvc

Cuestiones relacionadas