Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python threading Lock not working in simple example

I must be missing something here but this simple example of two threads trying to modify a global variable in a function is not giving the expected result:

from threading import Thread, Lock
some_var = 0

def some_func(id):
    lo = Lock()
    with lo:
        global some_var
        print("{} here!".format(id))
        for i in range(1000000):
            some_var += 1
        print("{} leaving!".format(id))


t1 = Thread(target=some_func, args=(1,))
t2 = Thread(target=some_func, args=(2,))
t1.start()
t2.start()
t1.join()
t2.join()
print(some_var)

outputs:

1 here!
2 here!
2 leaving!
1 leaving!
1352010

As you can see both threads enter the part that should be locked simultaneous and the incrementation of the globel variable 'some_var' gets mixed up because of that.

It looks like the Lock is just not working for some reason. For a range up to 10000 it is working but this is probably just because of the GIL not being released during such short calculations.

What is going on?

I'm using Python3.3.2 64bit

like image 714
lou Avatar asked Aug 06 '14 16:08

lou


People also ask

What does a threading lock do?

A lock allows you to force multiple threads to access a resource one at a time, rather than all of them trying to access the resource simultaneously.

How do I know if my Python lock is locked?

locked() is an inbuilt method of the Lock class of the threading module in Python. This method returns True if the lock is acquired by a thread else returns False. Parameter(s): None.

What happens if a thread is not joined Python?

A Python thread is just a regular OS thread. If you don't join it, it still keeps running concurrently with the current thread. It will eventually die, when the target function completes or raises an exception.


1 Answers

The Lock() function creates an entirely new lock - one that only the thread calling the function can use. That's why it doesn't work, because each thread is locking an entirely different lock.

Lock items are one of the few things that you can declare as a global without any problems, because you absolutely want every thread to see the same Lock(). You should try this instead:

from threading import Thread, Lock
some_var = 0
lo = Lock()

def some_func(id):
    global lo
    with lo:
        global some_var
        print("{} here!".format(id))
        for i in range(1000000):
            some_var += 1
        print("{} leaving!".format(id))
like image 53
TheSoundDefense Avatar answered Sep 17 '22 21:09

TheSoundDefense