views:

138

answers:

3

Hello all. I am starting with multi-threads in python(or at least it is possible that my script creates multiple threads). would this algorithm be the right usage of a Mutex? I haven't tested this code yet and it probably won't even work. I just want processData to run in a tread(one at time) and the main while loop to keep running, even if there is a tread in queue.

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

Edit: re-reading my code I can see that it is grossly wrong. but hey, that's why I am here asking for help.

A: 

You have to unlock your Mutex at sometime...

Guillaume Lebourgeois
+1  A: 

I don't know why you're using the Window's Mutex instead of Python's. Using the Python methods, this is pretty 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()

But note, because of the architecture of CPython (namely the Global Interpreter Lock) you'll effectively only have one thread running at a time anyway--this is fine if a number of them are I/O bound, although you'll want to release the lock as much as possible so the I/O bound thread doesn't block other threads from running.

An alternative, for Python 2.6 and later, is to use Python's multiprocessing package. It mirrors the threading package, but will create entirely new processes which can run simultaneously. It's trivial to update your example:

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()
Chris B.
I tried your code, and I get this error: with mutex: SyntaxError: invalid syntax. I guess I could use try: except: in my functionI am using python 2.4
Richard
`with` is Python 2.5, and `multiprocessing` is Python 2.6. Edited accordingly.
Chris B.
Thanks for all your help, if I could upvote you more then once I would. I upvoted all you comments :D they were helpful
Richard
A: 

ok this is the solution I came up with. Feel free to review and comment on the code:

import time
from threading import Thread
from threading import Lock
import mutex

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

Output:

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
Richard
There's a potential deadlock. If the print statement throws an Exception, you'll never release the mutex. You need to use `try/release` or `with` to ensure the lock is released. See my answer.
Chris B.
Also, there's no need to pass the mutex as an argument to the function. It's available in the global scope.
Chris B.