Locking around

Carl Banks pavlovevidence at gmail.com
Wed Aug 6 13:03:29 CEST 2008


On Aug 6, 6:34 am, Nikolaus Rath <Nikol... at rath.org> wrote:
> Nikolaus Rath <Nikol... at rath.org> writes:
> >> This should work, at least the idea is not flawed. However, I'd say
> >> there are too many locks involved. Rather, you just need a simple
> >> flag and the global lock. Further, you need a condition/event that
> >> tells waiting threads that you released some of the files so that it
> >> should see again if the ones it wants are available.
>
> > I have to agree that this sounds like an easier implementation. I
> > just have to think about how to do the signalling. Thanks a lot!
>
> Here's the code I use now. I think it's also significantly easier to
> understand (cv is a threading.Condition() object and cv.locked_keys a
> set()).
>
>     def lock_s3key(s3key):
>         cv = self.s3_lock
>
>         try:
>             # Lock set of locked s3 keys (global lock)
>             cv.acquire()
>
>             # Wait for given s3 key becoming unused
>             while s3key in cv.locked_keys:
>                 cv.wait()
>
>             # Mark it as used (local lock)
>             cv.locked_keys.add(s3key)
>         finally:
>             # Release global lock
>             cv.release()
>
>     def unlock_s3key(s3key):
>         cv = self.s3_lock
>
>         try:
>             # Lock set of locked s3 keys (global lock)
>             cv.acquire()
>
>             # Mark key as free (release local lock)
>             cv.locked_keys.remove(s3key)
>
>             # Notify other threads
>             cv.notify()
>
>         finally:
>             # Release global lock
>             cv.release()

Freaky... I just posted nearly this exact solution.

I have a couple comments.  First, the call to acquire should come
before the try block.  If the acquire were to fail, you wouldn't want
to release the lock on cleanup.

Second, you need to change notify() to notifyAll(); notify alone won't
cut it.  Consider what happens if you have two threads waiting for
keys A and B respectively.  When the thread that has B is done, it
releases B and calls notify, but notify happens to wake up the thread
waiting on A.  Thus the thread waiting on B is starved.


Carl Banks



More information about the Python-list mailing list