2010-07-22 13 views
41

Zaczynam od wielu wątków w pythonie (a przynajmniej jest możliwe, że mój skrypt tworzy wiele wątków). czy ten algorytm byłby właściwym użyciem Mutexa? Nie testowałem jeszcze tego kodu i prawdopodobnie nawet nie zadziała. Chcę tylko, aby processData działał w wątku (jeden na raz) i głównej pętli while, aby kontynuować działanie, nawet jeśli istnieje wątek w kolejce.Właściwe użycie muteksów w Pythonie

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 

Edycja: ponowne czytanie mojego kodu Widzę, że jest rażąco źle. ale hej, dlatego tu jestem, prosząc o pomoc.

+0

To jest bardzo trudne, aby dowiedzieć się, co próbujesz zrobić. Musisz dokładniej wyjaśnić swoje zamiary. –

+0

@Marcelo Cantos, przepraszam, prawdopodobnie masz rację. Chcę, aby mój kod w processData zaczął się w nowym bieżniku. Chcę tylko jeden wątek, aby móc przetwarzać dane w czasie i w kolejności, w której dane zostały wysłane do przetwarzania danych. Chcę również, aby pętla main while pozostała w pętli, podczas gdy inne wątki są w kolejce. – Richard

+0

@Richard: Dlaczego chcesz używać wątków, jeśli mimo wszystko masz zamiar serializować całe przetwarzanie? Co jest nie tak z prostą pętlą? Ponadto, dlaczego główny wątek ma pozostać w pętli? Po prostu wypali procesor, prawdopodobnie głodząc inne wątki. –

Odpowiedz

96

nie wiem dlaczego używasz Mutex oknie zamiast z Pythona. Używając metod Pythona, to jest całkiem prosta:

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() 

jednak pamiętać, że ze względu na architekturę CPython (mianowicie Global Interpreter Lock) skutecznie będziesz mieć tylko jeden wątek uruchomiony w czasie, w każdym razie - jeśli to jest w porządku pewna liczba z nich jest związana I/O, chociaż będziesz chciał zwolnić blokadę tak bardzo, jak to tylko możliwe, aby wątek związany z we/wy nie blokował uruchamiania innych wątków.

Alternatywą dla Pythona 2.6 i nowszych jest użycie pakietu Python multiprocessing. Odzwierciedla to pakiet threading, ale utworzy całkowicie nowe procesy, które będą działać jednocześnie. To trywialne zaktualizować swoją przykład:

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

Wypróbowałem twój kod i otrzymuję ten błąd: z mutex: SyntaxError: nieprawidłowa składnia. Chyba mógłbym użyć try: z wyjątkiem: w mojej funkcji używam python 2.4 – Richard

+4

'with' to Python 2.5, a' multiprocessing' to Python 2.6. Edytowane odpowiednio. –

+0

Dzięki za twoją pomoc, gdybym mógł cię zdobyć więcej niż raz. Przegłosowałem wszystkie twoje komentarze: D były pomocne – Richard

7

Musisz odblokować Mutex co kiedyś ...

12

To rozwiązanie wymyśliłem:

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 

wyjściowa:

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

Istnieje potencjalny impas. Jeśli instrukcja print zgłasza wyjątek, nigdy nie zwolni muteksu. Musisz użyć 'try/release' lub' with', aby upewnić się, że blokada została zwolniona. Zobacz moją odpowiedź. –

+2

Nie trzeba również przekazywać muteksu jako argumentu do funkcji. Jest dostępny w zasięgu globalnym. –

Powiązane problemy