Python threading lock not working in simple example
I need to be missing something, but this simple example of two threads trying to change a global variable in a function does not give 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 are entering the part that needs to be blocked at the same time and the increment of the globel variable 'some_var' gets mixed up because of this.
It looks like Lock doesn't work for some reason. For a range up to 10,000 it works, but that's probably only because the GIL is not being released during such short computations.
What's happening?
I am using Python3.3.2 64bit
source to share
The function Lock()
creates a completely new lock - one that only the thread calling the function can use. This is why it doesn't work, because each thread blocks a completely different lock.
Blocking elements are one of the few things you can declare as global without any problem, because you absolutely want every thread to see the same thing 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))
source to share
Or you can define a lock in your main () function. And pass it to the called function.
lock = threading.Lock() t1 = Thread(target=some_func, args=(1,lock)) t2 = Thread(target=some_func, args=(2,lock)) t1.start() t2.start()
Thus, there is only one lock. It's best to avoid globals whenever possible.
source to share