71 votes

Les verrous en code Python multithread sont-ils inutiles à cause de GIL

Si vous êtes en s'appuyant sur une implémentation de Python qui a un blocage de l'interpreteur Global (c'est à dire Disponible) et l'écriture du code multithread, avez-vous vraiment besoin de verrous à tous?

Si le GIL n'autorise pas plusieurs instructions qui seront exécutées en parallèle, ne serait pas de données partagée être inutile pour les protéger?

désolé si c'est une question stupide, mais c'est quelque chose que j'ai toujours demandé à propos de Python sur multi-processeur/de base des machines.

même chose devrait s'appliquer à tout autre langage de mise en œuvre est un GIL.

70voto

Will Harris Points 17002

Vous aurez toujours besoin de serrures si vous partagez l'état entre les threads. Le GIL ne protège que l'interprète à l'interne. Vous pouvez encore incompatible mises à jour dans votre propre code.

Par exemple:

#!/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

Ici, votre code peut être interrompu entre la lecture de l'état partagé (balance = shared_balance) et de l'écriture a changé résultat (shared_balance = balance), entraînant une perte de mise à jour. Le résultat est une valeur aléatoire pour l'état partagé.

Pour faire les mises à jour cohérentes, exécuter des méthodes serait nécessaire de verrouiller l'état partagé autour de la lecture-modification-écriture sections (à l'intérieur de la boucle) ou ont une certaine façon de détecter le moment où l'état partagé avait changé depuis qu'il a été lu.

23voto

Brian Points 48423

Sans le GIL juste protège python internes à partir de plusieurs threads de la modification de leur état. C'est un très faible niveau de verrouillage, suffisant pour garder python les structures propres à un état cohérent. Elle ne couvre pas la demande de blocage au niveau que vous aurez besoin pour couvrir fil de sécurité dans votre propre code.

L'essence de verrouillage est de veiller à ce qu'un bloc de code est exécuté par un thread. Le GIL applique ce pour des blocs de la taille d'un seul bytecode, mais en général, vous voulez que le verrou s'étendent sur un grand bloc de code que cela.

11voto

Bruno Gomes Points 885

Pour ajouter à la discussion:

Parce que le GIL, certaines opérations sont atomiques en Python et n'ont pas besoin d'une serrure.

http://www.python.org/doc/faq/library/#what-kinds-of-global-value-mutation-are-thread-safe

Comme indiqué par les autres réponses, cependant, vous avez encore besoin d'utiliser des verrous à chaque fois que la logique de l'application l'exige (par exemple dans un Producteur/Consommateur problème).

9voto

rcreswick Points 6429

Ce post décrit le GIL à un assez haut niveau:

D'intérêt particulier sont ces citations:

Tous les dix instructions (ce défaut peut être changé), à la base des communiqués de l' GIL pour le thread courant. À l' point, le système d'exploitation choisit un fil de tous les fils de la concurrence pour le verrouiller (éventuellement choisir le même thread que vient de publier le GIL – vous n'avez pas a aucun contrôle sur le thread choisit-on); ce thread acquiert la GIL, puis exécute une dizaine de bytecode.

et

Notez soigneusement que le GIL seulement limite pure code Python. Extensions (externe bibliothèques Python généralement écrit en C) peut être écrit que libérer le verrou, ce qui permet alors l'interpréteur Python pour exécuter séparément de l'extension jusqu'à l'extension rachète la serrure.

Il sonne comme le GIL fournit de moins en moins de cas possibles pour un changement de contexte, et fait du multi-core/processeur systèmes se comportent comme un seul cœur, pour chaque instance de l'interpréteur python, donc, oui, vous avez encore besoin d'utiliser des mécanismes de synchronisation.

8voto

David Eyk Points 3166

Le Mondial de l'Interprète de Verrouillage empêche les threads d'accéder à l' interprète simultanément (donc Disponible seulement jamais utilise qu'un seul core). Cependant, ce que je comprends, les fils sont toujours interrompue et planifiée de manière préventive, ce qui signifie que vous avez encore besoin d'écluses sur le partage des structures de données, de peur que votre fils marcher sur les pieds.

La réponse que j'ai rencontré à de nombreuses reprises que le multithreading en Python est rarement la peine de la surcharge, à cause de cela. J'ai entendu de bonnes choses au sujet de la PyProcessing projet, ce qui rend l'exécution de plusieurs processus en tant que "simple" comme le multithreading, avec des structures de données, des files d'attente, etc. (PyProcessing sera introduit dans la bibliothèque standard de la prochaine version 2.6 de Python comme le multitraitement module.) Cela vous permet de vous autour de la GIL, que chaque processus a son propre interprète.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X