105 votes

Utilisation correcte des mutex en Python

Je commence avec des threads multiples en python (ou du moins il est possible que mon script crée plusieurs threads). Serait-il judicieux d'utiliser un Mutex pour cet algorithme? Je n'ai pas encore testé ce code et il ne fonctionnera probablement pas de toute façon. Je veux juste que processData s'exécute dans un thread (un à la fois) et que la boucle principale while continue de s'exécuter, même s'il y a un thread en attente.

from threading import Thread
from win32event import CreateMutex
mutex = CreateMutex(None, False, "My Crazy Mutex")
while(1)
    t = Thread(target=self.processData, args=(some_data,))
    t.start()
    mutex.lock()

def processData(self, data)
    while(1)
        if mutex.test() == False:
            do some stuff
            break

Édition : En relisant mon code, je vois bien qu'il est complètement faux. Mais bon, c'est pourquoi je suis ici pour demander de l'aide.

224voto

Chris B. Points 14211

Je ne sais pas pourquoi vous utilisez le mutex de Windows au lieu de celui de Python. En utilisant les méthodes de Python, c'est assez simple :

from threading import Thread, Lock

mutex = Lock()

def processData(data):
    with mutex:
        print('Faire quelque chose')

while True:
    t = Thread(target = processData, args = (some_data,))
    t.start()

Mais notez, en raison de l'architecture de CPython (notamment le Global Interpreter Lock), vous aurez effectivement un seul thread s'exécutant à la fois de toute façon -- c'est normal si un certain nombre d'entre eux sont liés à l'I/O, bien que vous voudrez libérer le verrou autant que possible pour que le thread lié à l'I/O ne bloque pas les autres threads.

Une alternative, pour Python 2.6 et versions ultérieures, est d'utiliser le package multiprocessing de Python. Il reproduit le package threading, mais créera entièrement de nouveaux processus qui peuvent s'exécuter simultanément. Il est trivial de mettre à jour votre exemple :

from multiprocessing import Process, Lock

mutex = Lock()

def processData(data):
    with mutex:
        print('Faire quelque chose')

if __name__ == '__main__':
    while True:
        p = Process(target = processData, args = (some_data,))
        p.start()

21voto

Teoman shipahi Points 7988

Je voudrais améliorer réponse de chris-b un peu plus.

Voir ci-dessous pour mon code :

from threading import Thread, Lock
import threading
mutex = Lock()

def processData(data, thread_safe):
    if thread_safe:
        mutex.acquire()
    try:
        thread_id = threading.get_ident()
        print('\nTraitement des données :', data, "Identifiant du thread :", thread_id)
    finally:
        if thread_safe:
            mutex.release()

counter = 0
max_run = 100
thread_safe = False
while True:
    some_data = counter        
    t = Thread(target=processData, args=(some_data, thread_safe))
    t.start()
    counter = counter + 1
    if counter >= max_run:
        break

Lors de votre première exécution, si vous définissez thread_safe = False dans la boucle while, le mutex ne sera pas utilisé et les threads se chevaucheront dans la méthode print comme ci-dessous :

Non Thread safe

mais, si vous définissez thread_safe = True et l'exécutez, vous verrez que toutes les sorties s'affichent parfaitement ;

Thread safe

j'espère que cela vous aidera.

16voto

Richard Points 1905

Ceci est la solution que j'ai trouvée :

import time
from threading import Thread
from threading import Lock

def myfunc(i, mutex):
    mutex.acquire(1)
    time.sleep(1)
    print "Thread: %d" %i
    mutex.release()

mutex = Lock()
for i in range(0,10):
    t = Thread(target=myfunc, args=(i,mutex))
    t.start()
    print "boucle principale %d" %i

Sortie :

boucle principale 0
boucle principale 1
boucle principale 2
boucle principale 3
boucle principale 4
boucle principale 5
boucle principale 6
boucle principale 7
boucle principale 8
boucle principale 9
Thread: 0
Thread: 1
Thread: 2
Thread: 3
Thread: 4
Thread: 5
Thread: 6
Thread: 7
Thread: 8
Thread: 9

11voto

Vous devez déverrouiller votre Mutex à un moment donné...

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