2017-06-29 2 views
0

Regardez ce morceau de code:Python gil comportement étrange

from threading import Thread 
import time 

cpt = 0 

def myfunction(): 
    print("myfunction.start") 
    global cpt 
    for x in range(10): 
     cpt += 1 
     time.sleep(0.2) 
     print("cpt=%d" % (cpt)) 
    print("myfunction.end") 

thread1 = Thread(target=myfunction) 
thread2 = Thread(target=myfunction) 
thread1.start() 
thread2.start() 

Cette fonction est très basique qui lit/écriture d'une variable globale. Je cours 2 threads sur cette même fonction. J'ai lu que python n'est pas très efficace avec le multi-threading à cause de GIL, qui verrouille automatiquement les fonctions ou méthodes qui accèdent aux mêmes ressources. Donc, je pensais que python va d'abord exécuter thread1, puis thread2, mais je peux voir dans la sortie de la console que les 2 threads sont exécutés en parallèle. donc je ne comprends pas ce que gil est vraiment verrouillait ...

Merci

+2

Le GIL n'a rien à voir avec "accéder aux mêmes ressources" . –

+1

Les verrous GIL au niveau du code octet Python, pas les fonctions ou les méthodes. – cdarke

Répondre

2

C'est à cause de l'appel système sleep qui libère le CPU (de l'interprète et même « sorties » pendant un certain temps)

lorsque vous faites time.sleep(0.2), le thread en cours est suspendu par le système (pas par Python) pour une durée donnée, et l'autre thread est autorisé à fonctionner.

Notez que les print déclarations ou threading.current_thread() que vous pouvez insérer pour espionner les fils donnent aussi (brièvement) au système si les threads peuvent changer à cause de cela (souvenez-vous Schrodinger's cat). Le réel test serait ceci:

from threading import Thread 
import time 

cpt = 0 

def myfunction(): 
    global cpt 
    for x in range(10): 
     cpt += 1 
     time.sleep(0.2) 
    print(cpt) 

thread1 = Thread(target=myfunction) 
thread2 = Thread(target=myfunction) 
thread1.start() 
thread2.start() 

Ici, vous obtenez

20 
20 

ce qui signifie que chaque fil a travaillé pour augmenter le compteur à son tour.

commentaire maintenant la déclaration time.sleep(), et vous obtiendrez:

10 
20 

ce qui signifie que le premier fil a tout de plus en plus, a pris fin et laisser le second fil augmente les 10 autres chefs d'accusation. Aucun appel système (même print) ne garantit que le GIL fonctionne pleinement.

GIL n'induit pas de problème de performance, il empêche simplement 2 threads de fonctionner en parallèle. Si vous avez vraiment besoin d'exécuter du code python en parallèle, vous devez utiliser le module multiprocessing à la place (avec toutes ses contraintes, le décapage, le forking ...)

+0

Ok donc GIL ne verrouille que les appels internes python? Y a-t-il un très gros problème de performance avec gil comme je peux le lire? Merci – Bob5421

+0

vérifier ma dernière édition :) –