Thread Synchronization in Django
Is there any way to block a critical area like with Ja开发者_开发问答va synchronized in Django?
You can use locks to make sure that only one Thread will access a certain block of code at a time.
To do this, you simply create a Lock
object then acquire the lock before the block of code you want to synchronize. All the threads must have access to the same Lock
object for this to work. An example:
from threading import Lock, Thread
lock = Lock()
def do_something():
lock.acquire() # will block if another thread has lock
try:
# ... use lock
finally:
lock.release()
Thread(target=do_something).start()
Thread(target=do_something).start()
For more information , see http://effbot.org/zone/thread-synchronization.htm.
My approach is to use the locking features of the database. This also works with multiple server processes.
I define a model as:
from django.db import models
class ThreadSafe(models.Model):
key = m.CharField(max_length=80, unique=True)
And then a context manager function as:
from contextlib import contextmanager
from django.db.transaction import atomic
@contextmanager
def lock(key):
pk = ThreadSafe.objects.get_or_create(key=key)[0].pk
try:
objs = ThreadSafe.objects.filter(pk=pk).select_for_update()
with atomic():
list(objs)
yield None
finally:
pass
And then I have a thread/process safe lock by simply doing:
with lock("my_key"):
do_scary_stuff_here()
This requires a database with support for transactions.
Great article Justin, just one thing using python 2.5 makes this way easier
In Python 2.5 and later, you can also use the with statement. When used with a lock, this statement automatically acquires the lock before entering the block, and releases it when leaving the block:
from future import with_statement # 2.5 only
with lock: ... access shared resource
If you are using PostgreSQL, you could use advisory locks. Any process or thread could acquire or release this lock, assuming they are all connecting to the same PostgreSQL database. django-pglocks
takes this approach.
精彩评论