Showing posts with label lock. Show all posts
Showing posts with label lock. Show all posts

Thursday, August 9, 2007

Threading and Locks

This week, I've been bitten by a dead-lock bug in my website's code twice already, and I've decided to fix it, and to write about it, as it seems like a common problem when starting with threading. To use a thread lock in Python, the threading module provides a Lock class that has two methods: acquire() and release(). Usually, one would think that thread-unsafe code should be "protected" by the lock like this ("lo" is a Lock variable):
def do_something():
lo.acquire()
do_threadunsafe_operation()
lo.release()

The problem is, that if do_threadunsafe_operation() raises an exception, the lock will not be released, and therefore, all subsequent calls to do_something() will lock forever. You have to put the code in a try..finally block to make sure the lock gets released when the function ends:
def do_something():
lo.acquire()
try:
do_threadunsafe_operation()
finally:
lo.release()

In the Python Cookbook, there is also a decorator version of this, so when using Python 2.4 and above, and you like using decorators, try the sychronized decorator and "decorate" your function:
@synchronized(lo)
def do_threadunsafe_operation():
pass

Threads in Python are cool, and if you're careful using them, you can make your application run faster without affecting the stability or flow of your application. A lesson I learned last weekend when a bug with locking resulting in my WSGI app dead-locking and the website unreacheable.