Programación concurrente con Python

Monitores

Es posible disponer de monitores SC en Python, se estructuran en torno a la clase Condition. Un objeto de clase Condition soporta un cerrojo y un único wait-set.

Es un modelo similar al de monitores en Java con el API de concurrencia estándar, es por tanto, obligado el uso de condiciones de guarda.

Este modelo de hebras...

Python utiliza el Global Interpreter Lock (GIL). Los cual imposibilita el paralelismo real, olbiga a las hebras a ejecutarse secuencialmente e imposibilita ligrar speedups mayores a 1.

Concurrencia con procesos

Alternativa a threading y el GIL, usando el módulo multiprocessing. Libre del GIL → concurrencia real, pero a diferencia de las hebras los procesos no comportan memoria, se necesitan medios específicos (IPC) para compartir la memoria.

Instanciar un proceso rápidamente

Utilizando el contructor de la clase Process, recibe dos parámetros:

  • Una función/método con el código que el proceso debe ejecutar
  • La lista de parámetros que la función/método necesita
multiprocessing.Process(target=miFuncion, args=(arg1, arg2,..., argn))

multiprocessing crea dos intérpretes de python

Comunicación entre procesos

Existen dos técnicas para comunicar procesos, no se basan en el paradigma de memoria compartida, se basan en el paradigma de paso de mensajes.

Esto requiere tipo de estructura de datos ad-hoc como los cauces (pipes) o las colas. Básicamente son memorias accesibles para varios procesos, que deben crearse explícitamente, y que suelen residir en el espacio del kernel.

 Comunicación con pipes

Un cauce, pipe, es una zona de memoria del kernel, puede ser leída y escrita por varios procesos. Se basan en el paradigma de paso de mensajes, la comunicación utiliza send-receive.

 Comunicación con colas

Una cola es una estructura de datos FIFO compartida entre procesos, se gestiona con los métodos put y get. Es muy parecido a utilizar contenedores autosincronizados en Java.

 Procesos y ejecutores

El módulo multiprocessing permite utilizar un ejecutor de procesos, es ejecutor es dimensionable. Utiliza el método map() para enviar procesos al ejecutor.

Sincronización de procesos

Es posible sincronizar procesos de forma estándar, el módulo multiprocessing ofrece las clases Lock, Barrier y Condition.

Sin embargo, puesto que Python con procesos no utiliza un paradigma de memoria compartida, sino un paradigma de paso mensajes, el modelo de sincronización estándar con estas clases apenas se utiliza.