I want to share a variable between two threads using atomic operations in the interpreter, as described here http://effbot.org/zone/thread-synchronization.htm. A simple assignment (single bytecode operation) of a core data type should be thread safe, beacuse of the GIL in python < 3.2. So far the theory. The follwing code can be run in either master or slave mode (-m or -s). The master mode does constantly send data via UDP. The slave mode does create a thread to read data from a udp port and update a variable on each received packet.
The example code does pass the shared variable as an argument to the thread on creation. I’ve tried also by using a global variable or passing a thread local store to the thread.
The result is alwas the same. Inside the read_time_master thread the variable gets assigned. But in the main thread, the value of shared variable isn’t updated.
#!/usr/bin/env python
import socket
import itertools
import multiprocessing
from optparse import OptionParser
from time import sleep
PORT = 1666
def read_time_master(sock, time_master):
while True:
time_master = float(sock.recvfrom(1024)[0])
def main():
time_master = 0.0
p = OptionParser()
p.add_option('--master', '-m', action='store_true')
p.add_option('--slave', '-s', action='store_true')
options, arguments = p.parse_args()
if options.master or options.slave:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
if options.master:
sock.connect(('127.0.0.1', PORT))
if options.slave:
sock.bind(('0.0.0.0', PORT))
recv_thread = multiprocessing.Process(target=read_time_master, args=(sock, time_master))
recv_thread.start()
for time in itertools.count():
print time
if options.slave:
print "master: %f" % time_master # -> not updated from other thread
if options.master:
try:
sock.send(str(time))
except socket.error:
pass
sleep(1)
if options.master or options.slave:
sock.close()
if __name__ == '__main__':
main()
You’re using
multiprocessing, notthreading, which isn’t helping your situation. If you were usingthreading.Threadto create the background worker you’d probably be able to get what you needed by simply throwing in aglobal time_mastercall within the function that’s being controlled by your background operation. Because you’re usingmultiprocessing, notthreading, you will likely need to look into themultiprocessing.Queueclass for containers that you can use to pass information back and forth between your processes or to synchronize them. You can also create variables that are shared between the processes as well (all of this is covered in themultiprocessingdocumentation / examples at the Python Homepage