2010-07-22 19 views
41

Estoy empezando con varios hilos en python (o al menos es posible que mi script cree varios hilos). ¿Sería este algoritmo el uso correcto de un Mutex? Todavía no he probado este código y probablemente ni siquiera funcionará. Solo quiero que processData se ejecute en un hilo (uno a la vez) y el ciclo while principal para seguir ejecutándose, incluso si hay un hilo en la cola.Uso adecuado de mutexes en Python

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 

Editar: volver a leer mi código Puedo ver que está muy mal. pero oye, es por eso que estoy aquí pidiendo ayuda.

+0

Es muy difícil de averiguar lo que está intentando hacer. Tendrá que explicar su intención con más detalle. –

+0

@Marcelo Cantos, lo siento, probablemente tengas razón. Quiero que mi código en processData comience en una nueva banda de rodadura. Solo quiero que un hilo pueda procesar datos a la vez y en orden de qué datos se enviaron para procesar los datos. También quiero que el ciclo while principal mantenga el bucle mientras que otros hilos están en cola. – Richard

+0

@Richard: ¿Por qué desea utilizar subprocesos si planea serializar todos los procesos de todos modos? ¿Qué pasa con un simple bucle? Además, ¿por qué quieres que el hilo principal se mantenga en bucle? Simplemente quemará la CPU, posiblemente muriendo de hambre a otros hilos. –

Respuesta

96

No sé por qué estás usando mutex de la ventana en lugar de Python. Utilizando los métodos de Python, esto es bastante simple:

from threading import Thread, Lock 

mutex = Lock() 

def processData(data): 
    mutex.acquire() 
    try: 
     print('Do some stuff') 
    finally: 
     mutex.release() 

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

Pero tenga en cuenta, debido a la arquitectura de CPython (a saber, la Global Interpreter Lock) podrás efectivamente sólo tiene un hilo conductor a la vez de todos modos - esto está muy bien si varios de ellos están vinculados a E/S, aunque deseará liberar el bloqueo tanto como sea posible para que el hilo de E/S encuadernado no bloquee la ejecución de otros hilos.

Una alternativa, para Python 2.6 y posterior, es usar el paquete multiprocessing de Python. Refleja el paquete threading, pero creará procesos completamente nuevos que pueden ejecutar simultáneamente. Es trivial para actualizar su ejemplo:

from multiprocessing import Process, Lock 

mutex = Lock() 

def processData(data): 
    with mutex: 
     print('Do some stuff') 

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

He intentado tu código, y me sale este error: con mutex: SyntaxError: sintaxis no válida. Supongo que podría usar try: excepto: en mi función Estoy usando python 2.4 – Richard

+4

'con' es Python 2.5, y' multiprocesamiento' es Python 2.6. Editado en consecuencia. –

+0

Gracias por toda su ayuda, si pudiera votarte más de una vez, lo haría. Subí todos tus comentarios: D fueron útiles – Richard

7

Tienes que desbloquear el mutex en algún momento ...

12

Esta es la solución que se me ocurrió:

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 "main loop %d" %i 

Salida:

main loop 0 
main loop 1 
main loop 2 
main loop 3 
main loop 4 
main loop 5 
main loop 6 
main loop 7 
main loop 8 
main loop 9 
Thread: 0 
Thread: 1 
Thread: 2 
Thread: 3 
Thread: 4 
Thread: 5 
Thread: 6 
Thread: 7 
Thread: 8 
Thread: 9 
+5

Hay un punto muerto potencial. Si la instrucción print arroja una Excepción, nunca lanzará el mutex. Deberá usar 'try/release' o' with' para asegurarse de que se libere el bloqueo. Ver mi respuesta –

+2

Además, no es necesario pasar el mutex como argumento para la función. Está disponible en el alcance global. –