Djangoで同期されたJavaのように重要な領域をブロックする方法はありますか?
4 に答える
ロックを使用して、一度に1つのスレッドのみが特定のコードブロックにアクセスするようにすることができます。
これを行うには、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()
これには、トランザクションをサポートするデータベースが必要です。
すばらしい記事ジャスティン、Python2.5を使用することでこの方法が簡単になります
Python 2.5以降では、withステートメントを使用することもできます。ロックとともに使用すると、このステートメントはブロックに入る前に自動的にロックを取得し、ブロックを出るときにロックを解放します。
将来のインポートからwith_statement#2.5のみ
ロック付き:...共有リソースにアクセス
PostgreSQLを使用している場合は、アドバイザリロックを使用できます。すべてのプロセスまたはスレッドが同じPostgreSQLデータベースに接続していると仮定すると、このロックを取得または解放できます。 django-pglocks
このアプローチを取ります。