I have a script that creates a bunch of threads, runs a program to use the threads to run tasks from a queue, and returns something from each thread. I want to count how many of
successful+=1
is not a thread-safe operation. With multiple threads trying to increment a shared global variable, collisions may happen and successful
will not be incremented properly.
To avoid this error, use a lock:
lock = threading.Lock()
def foo():
global successful
while True:
...
with lock:
successful+=1
Here is some code to demonstrate that x += 1 is not threadsafe:
import threading
lock = threading.Lock()
x = 0
def foo():
global x
for i in xrange(1000000):
# with lock: # Uncomment this to get the right answer
x += 1
threads = [threading.Thread(target=foo), threading.Thread(target=foo)]
for t in threads:
t.daemon = True
t.start()
for t in threads:
t.join()
print(x)
yields:
% test.py
1539065
% test.py
1436487
These results do not agree and are less than the expected 2000000. Uncommenting the lock yields the correct result.