有没有办法像Django中的Java同步一样阻塞关键区域?
您可以使用锁来确保一次只有一个线程可以访问特定的代码块。
为此,您只需创建一个
Lock
对象,然后在要同步的代码块之前获取锁。所有线程必须能够访问同一个 Lock
对象才能正常工作。一个例子:
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()
有关更多信息,请参阅 http://effbot.org/zone/thread-synchronization.htm。
我的方法是使用数据库的锁定功能。这也适用于多个服务器进程。
我将模型定义为:
from django.db import models
class ThreadSafe(models.Model):
key = m.CharField(max_length=80, unique=True)
然后上下文管理器的功能如下:
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
然后我只需执行以下操作即可获得线程/进程安全锁:
with lock("my_key"):
do_scary_stuff_here()
这需要一个支持事务的数据库。
贾斯汀的好文章,只有一件事是使用 python 2.5 让这种方式变得更容易
在Python 2.5及更高版本中,您还可以使用with语句。当与锁一起使用时,该语句在进入块之前自动获取锁,并在离开块时释放锁:
from future import with_statement # 仅限 2.5
带锁: ...访问共享资源
如果您使用 PostgreSQL,则可以使用咨询锁。任何进程或线程都可以获取或释放此锁,假设它们都连接到同一个 PostgreSQL 数据库。
django-pglocks
采用这种方法。