Pregunta

Estoy limpiando una parte del código Python que escribí cuando era ... no tan bien informado. Principalmente estoy matando parte de la complejidad que se deriva de una comprensión incompleta de enhebrar en Python. Necesito hacer una lista de elementos compatibles con el proceso, y me gustaría hacerlo a través de listas inmutables, en lugar del enfoque de bloqueo habitual. Sé que los objetos inmutables son muy especiales con respecto a la rosca ya que todas las cuestiones de hilo de seguridad que rodean los cambios de estado incompletas simplemente desaparecen.

Por lo tanto, pregunto: ¿El código siguiente hilo de seguridad

?
class ImmutableList(object):
    def __init__(self):
        self._list = ()

    def __iter__(self):
        return self._list.__iter__()

    def append(self, x):
        self._list = self._list + tuple([x])

Creo que es, porque una nueva lista se construye cada vez. Si la lista se actualiza mientras que otro hilo está iterando a través de él, la lista de edad continuará siendo utilizado por el resto de la iteración. Esto está bien para mí, pero no puede ser para todos.

Además, es una buena idea? Sólo quiero aplicar esto a unas pocas situaciones en las que el tamaño de la lista es pequeña, y las listas no se cambian mucho (detectores de eventos vienen a la mente).

¿Fue útil?

Solución

En primer lugar, añadiendo a una lista que ya es seguro para subprocesos en la implementación de referencia CPython del lenguaje de programación Python. En otras palabras, mientras que la especificación del lenguaje no requiere que la clase lista sea seguro para subprocesos, es de todos modos. Así que a menos que estés usando Jython o IronPython o alguna otra aplicación Python así, entonces está bien.

En segundo lugar, también había necesidad de sobrecargar el resto de la lista de operaciones, tales como __setitem__ y __setslice__, etc. Estoy asumiendo que su aplicación se encarga de esto.

Por último, la respuesta a su pregunta es no: el código no es seguro para subprocesos. Considere la siguiente situación:

  • La lista contiene (5, 6)
  • Thread 1 intenta anexar 7, y el hilo 2 intenta anexar 8
  • Thread 1 constructos otra tupla (5, 6, 7) y antes de que se pueden asignar a _list, hay un cambio de contexto
  • Thread 2 realiza su asignación, por lo que la lista es ahora (5, 6, 8)
  • Tema 1 obtiene el control de la CPU atrás y asigna a _list, sobrescribiendo el append anterior. La lista es ahora (5, 6, 7) y la 8 se ha perdido.

La moraleja de esta historia es que usted debe utilizar el bloqueo y evitar la inteligencia.

Otros consejos

Una verdadera aplicación lista inmutable no permitirá que la estructura subyacente lista para cambiar, al igual que usted está aquí. Como @ [Eli Courtwright] señaló, su aplicación no es seguro para subprocesos. Esto es así porque en realidad no es inmutable. Para hacer una aplicación inmutable, utilización de métodos que han cambiado la lista, en vez volverían una nueva lista que refleja el cambio deseado.

Con respecto a su ejemplo de código, esto requeriría que hacer algo como esto:

class ImmutableList(object):
  def __init__(self):
    self._list = ()

  def __iter__(self):
    return self._list.__iter__()

  def append(self, x):
    return self._list + tuple([x])
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top