threads: not locking read-only objects

Robert Brewer fumanchu at amor.org
Sat Aug 7 02:07:37 EDT 2004


Jon Perez wrote:
> Hmmm... here's what's going on.  I have a dictionary of
> logged in users called 'whoison' that's updated in the main
> thread (and only in the main thread) with a:
> 
> whoison['username']="timeoflogin"  # to add someone new
> 
> and
> 
> del whoison['username']  # to remove someone who's logged out
> 
> 
> Do the above count as atomic?

Yes; however, that's not enough in your case. :)

> The worker threads do the following read-only operation:
> 
> for x in whoison:
>    print x,whoison[x]
> 
> Looking at the read-only code though I just realized
> something.... if a dictionary entry in 'whoison' is deleted
> by the main thread while the 'for x in whoison' is executing
> then what would happen?

You get an exception:

>>> import threading
>>> whoison = dict.fromkeys(xrange(100000))
>>> def iterate():
... 	for a in xrange(1000):
... 		for x in whoison:
... 			42
... 	print "Done"
... 	
>>> threading.Thread(None, iterate).start()
>>> del whoison[333]
>>> Exception in thread Thread-11:
Traceback (most recent call last):
  File "C:\Python23\lib\threading.py", line 436, in __bootstrap
    self.run()
  File "C:\Python23\lib\threading.py", line 416, in run
    self.__target(*self.__args, **self.__kwargs)
  File "<interactive input>", line 3, in iterate
RuntimeError: dictionary changed size during iteration


> Looks like I'm going to need a lock after all even for the
> read-only operations...?

Yup. Or use some other trick, like:

for k in whoison.keys():
    v = whoison.get(k)
    print k, v

...which iterates over a copy of the keys instead of the keys
themselves. Other, more complicated techniques exist. You'll soon
understand why many gurus declare concurrency to be one of the recurring
"hard problems" of programming. ;)


Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org



More information about the Python-list mailing list