あなたが観察できるものの一種である。このことから
>>> from threading import Thread
>>> from time import sleep
>>> liszt = ['first item', 'second item', 'third item', 'fourth item',
... 'plentee more items', "but I'm lazy"]
>>> def thread_one():
... for i in liszt:
... print 'Thread one found "%s"' % i
... sleep(1)
...
>>> def thread_two():
... sleep(0.5)
... print 'Thread two deleting first item.'
... del liszt[0]
... sleep(1)
... print 'Thread two deleting fourth item.'
... del liszt[3]
...
>>> Thread(target=thread_one).start(); Thread(target=thread_two).start()
Thread one found "first item"
Thread two deleting first item.
Thread one found "third item"
Thread two deleting fourth item.
Thread one found "fourth item"
Thread one found "but I'm lazy"
あなたが1つのスレッドでリストを変更すると、他のスレッドでイテレータに影響を与えていることがわかります。最初のアイテムを削除すると、イテレータはアイテムをスキップし、次のアイテムを削除すると、イテレータには表示されません。
これはいくつかの仕組みのモデルです。私はこれを明示的に提供しているわけではありませんが、あなたはこれを観測から取り除くことができます。
State: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Iterator position:^
次の項目に移動します。
State: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Iterator position: ^
最初の項目を削除します。
State: [2, 3, 4, 5, 6, 7, 8, 9, 10]
Iterator position: ^
次の項目に移動します。
State: [2, 3, 4, 5, 6, 7, 8, 9, 10]
Iterator position: ^
5番目の項目を削除します。
State: [2, 3, 4, 5, 7, 8, 9, 10]
Iterator position: ^
等が挙げられる。スレッド化に関しては、1つのスレッドで実行するのか、複数のスレッドで実行するのかは関係ありません。確かに、アイテムが削除されているかどうかにかかわらず競合状態があるかもしれませんが、それでも同じように動作します。
あなたが繰り返しの内部に慣れていない場合は、iter
を満たしています。実際にはfor x in y
はiter(y)
を繰り返しています。したがって、あなたが望むならiter(liszt)
listiteratorオブジェクトで遊ぶことができます。リスト上で反復する間にnext()
を使用して再生します。インタラクティブなPythonコンソールのfor-loopよりも便利です。
*試しましたか? –
@ChrisMorgan競合状態のバグは悪名高く見つけにくいです。したがって、明らかにエラーがあることを示すだけで、それ以外の場合は表示されない可能性があります。さらに悪いことに、cpythonのGILは一貫してエラーを隠すでしょう。 – phihag
@ChrisMorgan私は現在のプロジェクトでこれを思いついたが、これは致命的なエラーを引き起こすものではなく、真実を明らかにする簡単で説得力のある例は見つけられない。 – onemach