Mutable global state and threads
Kev Dwyer
kevin.p.dwyer at gmail.com
Wed Jan 4 01:41:40 EST 2017
Hello List,
I came across some threading code in Some Other place recently and wanted to
sanity-check my assumptions.
The code (below) creates a number of threads; each thread takes the last
(index -1) value from a global list of integers, increments it by one and
appends the new value to the list.
The originator of the code expected that when all the threads completed, the
list would be an ascending sequence of integers, for example if the original
list was [0] and two threads mutated it twice each, the final state would be
[0, 1, 2, 3, 4].
Here is a version of the code (slightly simplified and modified to allow
changing the number of threads and mutations).
import sys
import threading
class myThread(threading.Thread):
def __init__(self, nmutations):
threading.Thread.__init__(self)
self.nmutations = nmutations
def run(self):
mutate(self.nmutations)
# print (L)
return
def mutate(nmutations):
n = nmutations
while n:
L.append(L[-1 ]+ 1)
n -= 1
return
def main(nthreads=2, nmutations=2):
global L
L = [0]
threads = [myThread(nmutations) for i in range(nthreads)]
for t in threads:
t.start()
for t in threads:
t.join()
print(L)
assert L == list(range((nthreads * nmutations) + 1))
if __name__ == '__main__':
nthreads, nmutations = int(sys.argv[1]), int(sys.argv[2])
main(nthreads, nmutations)
Firstly, is it true that the statement
L.append(L[-1 ]+ 1)
is not atomic, that is the thread might evaluate L[-1] and then yield,
allowing another thread to mutate L, before incrementing and appending?
Secondly, the original code printed the list at the end of a thread's run
method to examine the state of the list. I don't think this would work
quite as expected, because the thread might yield after mutating the list
but before printing, so the list could have been mutated before the print
was executed. Is there a way to display the state of the list before any
further mutations take place?
(Disclaimer: I understand that sanity, mutable global state and threads are
unlikely bedfellows and so promise never to try anything like this in
production code).
Cheers,
Kev
More information about the Python-list
mailing list