<div class="gmail_quote"><br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div class="im">
<br>
</div>Sure, but I think you're timing the wrong thing here.  You would only<br>
allocate the lock relatively rarely - it's the overhead of *acquiring*<br>
the lock that's the real problem.<br>
<br>
   rfk@durian:~$ python -m timeit -s "from threading import Lock; l = Lock()" "l.acquire(); l.release()"<br>
   1000000 loops, best of 3: 0.378 usec per loop<br>
<br>
Compare to one of my favourite dict methods, setdefault:<br>
<br>
   rfk@durian:~$ python -m timeit -s "d = dict()" "d.setdefault('hello','world')"<br>
   10000000 loops, best of 3: 0.189 usec per loop<br>
<br>
<br>
In the same ballpark really.<br>
<div class="im"><br></div></blockquote><div><br><br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div class="im">
<br>
</div>I've managed to avoid locking in some cases by using dict.setdefault()<br>
as a kind of atomic test-and-set operation.  It's not a full<br>
compare-and-swap but you could implement a simple locking scheme using<br>
it like this:<br>
<br>
<br>
  class PretendLock:<br>
      def __init__(self):<br>
          self.d = dict()<br>
      def acquire(self):<br>
          myid = threading.currentThread().ident<br>
          while self.d.setdefault("owner",myid) != myid:<br>
              pass<br>
      def release(self):<br>
          del self.d["owner"]<br>
<br>
<br>
This depends on some peculiarities of the CPython implementation that<br>
aren't guaranteed by the language spec - namely that thread switches<br>
can't happen while executing C code, that dict.setdefault is implemented<br>
in C, and that is can calculate the hash of a string key without calling<br>
back out to python code.<br>
<br>
Usually, it's not worth it.  The one time I use this regularly is for<br>
lazy object initialisation, e.g. something like this:<br>
<br>
  def get_my_object(key):<br>
      try:<br>
         return objects[key]<br>
      except KeyError:<br>
         return objects.setdefault(key,create_my_object(key))<br>
<br>
If two threads happen to try initialising the object at the same time,<br>
only one will wind up in the dict and being used; the other will be<br>
discarded and garbage-collected.<br></blockquote><br>Thanks Ryan,<br>
<br>
Agreed, I was timing the wrong thing - but largely because I wasn't sure
 what to time against. setdefault certainly seems to be a candidate for 
something to time. Even so, setdefault wins.<br>
<br>Though, I wouldn't want to use PretendLock in this case... it doesn't seem that having the spin loop would justify reducing reducing the lock allocation overhead in a no-contention scenario.<br><br>Yes, get_my_object is a good trick. I did just that to avoid instantiating extra locks in one scenario.<br>
<br></div>--<br clear="all">Zachary Burns<br>(407)590-4814<br>Aim - Zac256FL<br>Production
 Engineer<br>Zindagi Games<br>