Algunas discusiones en otra pregunta me han alentado a comprender mejor los casos en los que se requiere el bloqueo en programas de Python multiproceso.¿Hay algún caso en el que los subprocesos de Python puedan manipular de forma segura el estado compartido?
por this artículo sobre enhebrar en Python, tengo varios ejemplos sólidos y comprobables de errores que pueden ocurrir cuando varios hilos acceden al estado compartido. El ejemplo de condición de carrera proporcionado en esta página implica carreras entre hilos que leen y manipulan una variable compartida almacenada en un diccionario. Creo que el caso de una carrera aquí es muy obvio, y afortunadamente es eminentemente comprobable.
Sin embargo, no he podido evocar una condición de carrera con operaciones atómicas tales como listas añadidas o incrementos variables. Esta prueba intenta exhaustivamente para demostrar una carrera tan:
from threading import Thread, Lock
import operator
def contains_all_ints(l, n):
l.sort()
for i in xrange(0, n):
if l[i] != i:
return False
return True
def test(ntests):
results = []
threads = []
def lockless_append(i):
results.append(i)
for i in xrange(0, ntests):
threads.append(Thread(target=lockless_append, args=(i,)))
threads[i].start()
for i in xrange(0, ntests):
threads[i].join()
if len(results) != ntests or not contains_all_ints(results, ntests):
return False
else:
return True
for i in range(0,100):
if test(100000):
print "OK", i
else:
print "appending to a list without locks *is* unsafe"
exit()
He corrido la prueba anterior sin fallo (100x 100k APPENDs multihilo). ¿Alguien puede hacer que falle? ¿Hay alguna otra clase de objeto que se pueda comportar incorrectamente a través de una modificación atómica, incremental por hilos?
¿Estas semánticas implícitamente 'atómicas' se aplican a otras operaciones en Python? ¿Está esto directamente relacionado con el GIL?
Las pruebas no son un método válido para probar la corrección en aplicaciones concurrentes. Es muy fácil para cualquier prueba en particular intercalar la ejecución de una manera inesperadamente predecible que nunca desencadenaría el problema, sin embargo, el más pequeño de los cambios en el código (es decir.al extenderlo a una situación del mundo real) podría mostrar instantáneamente el defecto. La corrección del software concurrente debe ser probada, no probada. – Kylotan