私はあるスレッドのループでロックを獲得しているアプリケーションを持っていて、 タスクを実行しています。また、時々 からロックを取得したい第2のスレッドもあります。問題は、この2番目のスレッドはほとんど最初のものがほぼ常に最初にロックするので、 がその作業を実行する機会をほとんど得られないことです。私は 次のコードは、私が言うことをしようとしているものを明確に願っています:アプリケーションがになるPythonのループでロックしている間のスレッドの飢餓
import time
from threading import Lock, Thread
lock = Lock()
def loop():
while True:
with lock:
time.sleep(0.1)
thread = Thread(target=loop)
thread.start()
before = time.time()
lock.acquire()
print('Took {}'.format(time.time() - before))
場合print
あなたはそれが道を超える ちょうど0.1秒を必要としていることに気づくでしょう。しかし時々、それは無限に待つだけです。私はこれをPython 2.7.11とPython 3.4.3の両方でDebian Linux 8でテストしました。これは同じように動作します。
この動作は私にとっては直感的です。結局のところ、ロックがリリースされたときに がloop
になると、lock.acquire
はすでにリリースを待っていたので、すぐに はロックを取得するはずです。しかし、その代わりに、 の解放の瞬間にループがリリースを待っていなくても、最初にループが というロックを取得するように見えます。
私が見つけた解決策は、ロック解除状態での各ループ反復の間スリープ状態にありませんが、エレガントな解決策として私に当たらないよう 、どちらもそれは は何が起こっているのか私に説明ありません。
私には何が欠けていますか?
相互排他ではなく確定的な動作をしたい場合は、 'Lock'は使用するオブジェクトではありません。' time.sleep(0) 'を発行することで強制的にタスク切り替えができるかもしれませんが、それはいくつかのプラットフォームで失敗することを確認します.. – thebjorn
まあ、私は、私はちょうど2つのスレッドがロックを待っているとき、それはすぐに別のロックが解除された後にそれを得ることがわかった。私はなぜそれがそうでないのだろうと思います。また、あなたは、使用するのに適したものは何だろうと思いますか? –
なぜそれが起こっているのか説明するのは難しいですが、もし私が推測するなら、whileループは、relaseコードが待機中のスレッドの中で選択されるまでにaquireを再度呼び出すことを管理するようなタスクスイッチと関係します。しかし、それはちょうど推測です。 – thebjorn