Aquí es el tipo de cosas se pueden observar:
>>> from threading import Thread
>>> from time import sleep
>>> liszt = ['first item', 'second item', 'third item', 'fourth item',
... 'plentee more items', "but I'm lazy"]
>>> def thread_one():
... for i in liszt:
... print 'Thread one found "%s"' % i
... sleep(1)
...
>>> def thread_two():
... sleep(0.5)
... print 'Thread two deleting first item.'
... del liszt[0]
... sleep(1)
... print 'Thread two deleting fourth item.'
... del liszt[3]
...
>>> Thread(target=thread_one).start(); Thread(target=thread_two).start()
Thread one found "first item"
Thread two deleting first item.
Thread one found "third item"
Thread two deleting fourth item.
Thread one found "fourth item"
Thread one found "but I'm lazy"
De esto se puede ver que la modificación de la lista en un único hilo afectó el iterador en el otro hilo; Al eliminar el primer elemento, el iterador omitió un elemento y, al eliminar un elemento futuro, no se verá en el iterador porque ya no está.
Aquí hay un modelo de cómo funciona esto; No estoy brindando código para esto de manera explícita, pero puedes resolverlo a partir de la observación.
State: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Iterator position:^
Ir al artículo siguiente.
State: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Iterator position: ^
Borrar el primer elemento.
State: [2, 3, 4, 5, 6, 7, 8, 9, 10]
Iterator position: ^
Ir al artículo siguiente.
State: [2, 3, 4, 5, 6, 7, 8, 9, 10]
Iterator position: ^
Eliminar el quinto elemento.
State: [2, 3, 4, 5, 7, 8, 9, 10]
Iterator position: ^
Et cetera. En el tema de enhebrar, no importa si lo haces en un hilo o en varios hilos. Claro, puede tener una condición de carrera sobre si el elemento se borra o no, pero sigue funcionando de la misma manera.
Si no está familiarizado con las partes internas de la iteración, conozca iter
. for x in y
itera sobre iter(y)
, en realidad. Por lo tanto, puede jugar con el objeto de lista de elementos iter(liszt)
si lo desea, usando next()
en él mientras juega con la lista que está iterando. Más conveniente que un for-loop en la consola interactiva de Python.
¿Has * probado *? –
@ChrisMorgan Los errores de condición de carrera son muy difíciles de encontrar. Por lo tanto, intentarlo solo puede mostrar que hay un error obvio y que no puede mostrar lo contrario. Peor aún, el GIL de cpython ocultará los errores consistentemente. – phihag
@ChrisMorgan Se me ocurre esto en mi proyecto actual, pero esto no desencadena un error fatal y no puedo encontrar un ejemplo simple pero persuasivo para revelar la verdad. – onemach