Si confía en una implementación de Python que tiene un bloqueo de intérprete global (es decir, CPython) y escribe código multiproceso, ¿realmente necesita bloqueos?
Si el GIL no permite que se ejecuten varias instrucciones en paralelo, ¿no sería innecesario proteger los datos compartidos?
lo siento si esta es una pregunta tonta, pero es algo que siempre me he preguntado sobre Python en máquinas multiprocesador / núcleo.
lo mismo se aplicaría a cualquier otra implementación de lenguaje que tenga un GIL.
Solución
Seguirá necesitando bloqueos si comparte el estado entre subprocesos. El GIL solo protege al intérprete internamente. Aún puede tener actualizaciones inconsistentes en su propio código.
Por ejemplo:
#!/usr/bin/env python
import threading
shared_balance = 0
class Deposit(threading.Thread):
def run(self):
for _ in xrange(1000000):
global shared_balance
balance = shared_balance
balance += 100
shared_balance = balance
class Withdraw(threading.Thread):
def run(self):
for _ in xrange(1000000):
global shared_balance
balance = shared_balance
balance -= 100
shared_balance = balance
threads = [Deposit(), Withdraw()]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
print shared_balance
Aquí, su código puede interrumpirse entre la lectura del estado compartido () y la escritura del resultado modificado (), lo que provoca una actualización perdida. El resultado es un valor aleatorio para el estado compartido.balance = shared_balance
shared_balance = balance
Para que las actualizaciones sean coherentes, los métodos de ejecución tendrían que bloquear el estado compartido alrededor de las secciones de lectura,modificación-escritura (dentro de los bucles) o tener alguna forma de detectar cuándo había cambiado el estado compartido desde que se leyó.
Otras respuestas
Piénsalo de esta manera:
En una computadora con un solo procesador, el subproceso múltiple ocurre suspendiendo un subproceso e iniciando otro lo suficientemente rápido como para que parezca que se está ejecutando al mismo tiempo. Esto es como Python con el GIL: solo un hilo se está ejecutando realmente.
El problema es que el hilo se puede suspender en cualquier lugar, por ejemplo, si quiero calcular b = (a + b) * 3, esto podría producir instrucciones algo como esto:
1 a += b
2 a *= 3
3 b = a
Now, lets say that is running in a thread and that thread is suspended after either line 1 or 2 and then another thread kicks in and runs:
b = 5
Then when the other thread resumes, b is overwritten by the old computed values, which is probably not what was expected.
So you can see that even though they’re not ACTUALLY running at the same time, you still need locking.