32

次のリンクを参照してください:http://docs.python.org/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe

私は次のことを知りたかった:

(x, y) = (y, x)

cPythonでアトミックが保証されます。(xとyは両方ともPython変数です)

4

2 に答える 2

58

どれどれ:

>>> x = 1
>>> y = 2
>>> def swap_xy():
...   global x, y
...   (x, y) = (y, x)
... 
>>> dis.dis(swap_xy)
  3           0 LOAD_GLOBAL              0 (y)
              3 LOAD_GLOBAL              1 (x)
              6 ROT_TWO             
              7 STORE_GLOBAL             1 (x)
             10 STORE_GLOBAL             0 (y)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE    

それらがアトミックであるようには見えません。xとyの値は、バイトコード間LOAD_GLOBAL、前または後ROT_TWO、およびバイトコード間で別のスレッドによって変更される可能性がありSTORE_GLOBALます。

2つの変数をアトミックに交換する場合は、ロックまたはミューテックスが必要です。

経験的証拠を望む人のために:

>>> def swap_xy_repeatedly():
...   while 1:
...     swap_xy()
...     if x == y:
...       # If all swaps are atomic, there will never be a time when x == y.
...       # (of course, this depends on "if x == y" being atomic, which it isn't;
...       #  but if "if x == y" isn't atomic, what hope have we for the more complex
...       #  "x, y = y, x"?)
...       print 'non-atomic swap detected'
...       break
... 
>>> t1 = threading.Thread(target=swap_xy_repeatedly)
>>> t2 = threading.Thread(target=swap_xy_repeatedly)
>>> t1.start()
>>> t2.start()
>>> non-atomic swap detected
于 2010-04-12T15:16:24.533 に答える
4

はい、そうなります。

私は正直に立っています。

KragenSitakerは次のように書いています。

イディオムの使用を推奨する人

spam, eggs = eggs, spam

スレッドセーフなスワップを取得します。これは本当に機能しますか?(...)
したがって、このスレッドが最初のLOAD_FAST
と最後のSTORE_FASTの間のどこかで制御を失った場合、値は別のスレッド
によって「b」に格納され、その後失われる可能性があります。これを防ぐものは何もありません
ね。

いいえ。一般に、単純な割り当てでさえ、必ずしもスレッドセーフであるとは限りません。割り当てを実行すると、オブジェクトに対して特別なメソッドが呼び出され、それ自体が多くの操作を必要とする場合があるためです。 オブジェクトがその「状態」値を内部的にロックしていることを願っていますが、常にそうであるとは限りません。

しかし、それは特定のアプリケーションで「スレッドセーフ」が何を意味するかによって実際に決定されます。なぜなら、私の考えでは、そのような安全性には多くのレベルの粒度があり、「スレッドセーフ」について話すのは難しいからです。Pythonインタープリターが無料で提供するのは、組み込みのデータ型がネイティブスレッドを使用している場合でも内部の破損から安全である必要があるということだけです。言い換えると、2つのスレッドに a=0xffとがある場合、aはどちらか一方になりますが、aが保護されていない場合に他の言語で発生する可能性があるため、a=0xff00誤って発生することはありません。0xffff

そうは言っても、Pythonは、エッジに少し住んでいて、使用中の実際のオブジェクトへの依存関係を暗示している場合は、正式なロックなしで非常に多くのことを回避できるような方法で実行される傾向があります。しばらく前に、これらの線に沿ってまともな議論がありました-とりわけ「クリティカルセクションとミューテックス」スレッドについてgroups.google.comを検索してください。

個人的には、マルチスレッドアプリケーションで共有状態を明示的にロックします(または、スレッド間で共有情報を適切に交換するために設計された構造を使用します)。Queue.Queue私の考えでは、これは将来のメンテナンスと進化に対する最善の保護です。

---デビッド

于 2010-04-12T15:14:31.033 に答える