33

with ステートメントを使用して共有ロックを実行しようとしています

def someMethod(self, hasLock = False):
     with self.my_lock:
         self.somethingElse(hasLock=True)


def somethingElse(self, hasLock = False):
    #I want this to be conditional...
    with self.my_lock:
          print 'i hate hello worlds"

意味がある?私は基本的に、まだロックを持っていない場合にのみ実行したいと考えています。

これを達成できることに加えて、それは悪い設計ですか? 自分自身を取得/解放するだけですか?

4

5 に答える 5

59

threading.RLock再入可能であるa を使用するだけで、同じスレッドで複数回取得できます。

http://docs.python.org/library/threading.html#rlock-objects

明確にするために、サンプルコードと同じようにRLock、ステートメントで使用されています。with

lock = threading.RLock()

def func1():
    with lock:
        func2()

def func2():
    with lock: # this does not block even though the lock is acquired already
        print 'hello world'

これが悪い設計であるかどうかについては、より多くのコンテキストが必要です。両方の関数がロックを取得する必要があるのはなぜですか? func2以外の何かによって呼び出されるのはいつfunc1ですか?

于 2011-03-03T19:47:47.970 に答える
7

Pythonorショート サーキットであるため、ロックを条件付きにすることができます。

def somethingElse(self, hasLock = False):
    #I want this to be conditional...
    with hasLock or self.my_lock:
          print 'i hate hello worlds'

with残念ながら、ブール値はステートメントからの有効な戻り値ではないため、それほど簡単ではありません。ブール値をラップするには、 __enter__andを使用してクラスを作成する必要があります。__exit__True

これは、私がテストしていない実装の 1 つです。

from contextlib import contextmanager

@contextmanager
def withTrue():
    yield True

def withbool(condition):
    if condition:
        return withTrue()
    return False

def somethingElse(self, hasLock = False):
    with withbool(hasLock) or self.my_lock():
          print 'i hate hello worlds'

これは非常に単純なものの多くのボイラープレートであるため、RLock ソリューションが勝者のように見えます。ただし、このソリューションは別のコンテキストで役立つ場合があります。

于 2011-03-03T19:49:29.327 に答える
2

acquire()with ステートメントを使用することは、andrelease()関数だけよりも優れています。これにより、エラーが発生した場合にロックが解除されます。

于 2011-03-03T19:45:43.487 に答える
2

なぜだめですか:

def someMethod(self):
     with self.my_lock:
         self.somethingNoLock()

def somethingElse(self):
    with self.my_lock:
         self.somethingNoLock()

def somethingNoLock(self):
    print 'i hate hello worlds"

私のソリューションではsomeMethodとは同じですが、一般的には異なることに注意してください。ロックの取得と解放が複数回繰り返されないように、somethingElse別のラッパーを配置できます。somethingNoLock

これははるかに単純で簡単です。再入可能なロック ハンマーが利用できるという理由だけで、それを釘付けにするためのより簡単で壊れにくい方法がある場合は、それを使用することはお勧めしません。

rlock のより具体的な批判は、再入可能なロックを作成する行が、再入可能な方法でロックを取得しているコードから遠く離れているということです。再入可能ロックを再入可能ではない別のロックと合体させたり、ロックを作成する行を変更したりすると、これは少し脆弱です。

于 2016-07-13T10:09:06.793 に答える
1

ロックは完全なリソース取得パターンであるため、withステートメントはロックを実装する優れた方法です。あなたの現在の例はうまくいきませんが。内のifステートメントの前後にステートメントが必要になります。withsomethingElse()

于 2011-03-03T19:48:57.473 に答える