Reputation: 1840
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
Upvotes: 10
Views: 12177
Reputation: 51
Or you can define the 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()
This way there is only one lock. It is better to avoid global variables whenever possible.
Upvotes: 3
Reputation: 63
Every time your function is getting called, a new lock is getting created hence you will have different locks for each different thread. The Lock object should be created globally because every thread should be able to see if the same lock is held up by another. Try moving you lock object creation as global lock!
Upvotes: 5
Reputation: 6945
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))
Upvotes: 14