2010-02-09 10 views

Respuesta

39

Debe implementar su propio bloqueo para todas las variables compartidas que se modificarán en Python. No tiene que preocuparse por leer las variables que no se modificarán (es decir, las lecturas simultáneas son correctas), por lo que los tipos inmutables (frozenset, tuple, str) son probablemente seguros, pero no haría daño. Para las cosas que va a cambiar: list, set, dict, y la mayoría de los demás objetos, debe tener su propio mecanismo de bloqueo (mientras que las operaciones in situ están bien en la mayoría de estos, los hilos pueden provocar errores súper desagradables - también podría implementar el bloqueo, es bastante fácil).

Por cierto, no sé si usted sabe esto, pero es muy fácil de bloqueo en Python - Crear un objeto threading.lock, y luego se puede adquirir/liberar de esta manera:

import threading 
list1Lock = threading.Lock() 

with list1Lock: 
    # change or read from the list here 
# continue doing other stuff (the lock is released when you leave the with block) 

En Python 2.5, do from __future__ import with_statement; Python 2.4 y antes no la tienen, así que querrá poner la adquisición()/release() llama en try:...finally: bloques:

import threading 
list1Lock = threading.Lock() 

try: 
    list1Lock.acquire() 
    # change or read from the list here 
finally: 
    list1Lock.release() 
# continue doing other stuff (the lock is released when you leave the with block) 

Some very good information about thread synchronization in Python.

+12

Creo que, para alguien que no ha utilizado bloqueos de enhebrado antes, debe tenerse en cuenta que el bloqueo (en su ejemplo, 'list1Lock') debe * compartirse * entre los hilos, para que funcione correctamente. Dos bloqueos independientes, uno para cada hilo, no bloquearían nada, solo agregarían una sobrecarga tonta. – tzot

+0

¿No debería ser este: con list1Lock: # Hacer cosas –

+0

@ slack3r Good call! –

3

Son seguros para subprocesos siempre que no deshabilite el GIL en el código C para el subproceso.

+5

Este es un detalle de implementación de CPython que no debe retransmitirse. Posiblemente va a tener posibilidades en el futuro y otras implementaciones no lo tienen. –

+0

Georg: este aspecto de la pitón me aterroriza. No importa todos los errores que saldrán de los programas java cuando 8 núcleos se vuelvan comunes en el escritorio: ¿qué sucede cuando GIL se elimina y las aplicaciones de python multiproceso se ejecutan repentinamente en 8 cajas de núcleos? – Ben

+3

No debería aterrorizar a nadie si no pretende que su código es seguro para subprocesos cuando claramente no lo es. :) – Kylotan

7

Sí, pero todavía hay que tener cuidado, por supuesto

Por ejemplo:

Si dos hilos están compitiendo para pop() de una lista con sólo un elemento, un hilo conseguir el artículo con éxito y el otra recibirá IndexError

Código como este no es seguro para subprocesos

if L: 
    item=L.pop() # L might be empty by the time this line gets executed 

debe wr ite it like this

try: 
    item=L.pop() 
except IndexError: 
    # No items left 
+5

Quiero que pop() sea seguro para la tarea, pero no puedo encontrar este hecho en ningún lugar de la documentación. ¿Alguien puede ayudarme a obtener este reclamo antes de tomarlo como un evangelio? –

+0

¿De verdad? list.pop() no es seguro para subprocesos? Vi otro artículo que decía lo contrario. http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm –

+0

@ Zhongjun'Mark'Jin dijo que ES seguro para hilos ... pero eso no significa no tienes que considerar los otros hilos. Si un hilo aparece el último elemento y luego otro hilo intenta abrir también, obtendrá IndexError, como él dice. – fantabolous

Cuestiones relacionadas