マルチスレッドの Python プログラムを作成しています。このプログラムでは、ワーカー スレッドを起動して入力データのリストを処理しています。それらが処理するデータはネットワーク操作を必要とするため、実質的に I/O バウンドになります (したがって、GIL は私にとって問題ではありません)。
複数のワーカー スレッドが明らかに同じ入力を受信しているという問題が発生していますが、その理由がわかりません。私が知る限り、スレッド間でスレッドセーフでないデータを共有していません。
私がやろうとしていることの最小化されたバージョンを作成しました。このプログラムは、I/O などを何も実行せずに問題を示します。
#!/usr/bin/env python
import threading
import logging
import time
logging.basicConfig(level=logging.DEBUG,
format="%(threadName)-10s %(levelname)-7s %(message)s")
sema = threading.Semaphore(10)
# keep track of already-visited data in worker threads
seen = []
seenlock = threading.Lock()
def see(num):
try:
logging.info("see: look at %d", num)
with seenlock:
if num in seen:
# this should be unreachable if each thread processes a unique number
logging.error("see: already saw %d", num)
else:
seen.append(num)
time.sleep(0.3)
finally:
sema.release()
def main():
# start at 1, so that the input number matches the log's "Thread-#"
for i in xrange(1, 100):
sema.acquire() # prevent more than 10 simultaneous threads
logging.info("process %d", i)
threading.Thread(target=lambda: see(i)).start()
if __name__ == '__main__': main()
出力の一部:
MainThread INFO process 1
MainThread INFO process 2
Thread-1 INFO see: look at 2
Thread-2 INFO see: look at 2
MainThread INFO process 3
Thread-2 ERROR see: already saw 2
MainThread INFO process 4
Thread-3 INFO see: look at 4
Thread-4 INFO see: look at 4
MainThread INFO process 5
Thread-4 ERROR see: already saw 4
Thread-5 INFO see: look at 5
MainThread INFO process 6
Thread-6 INFO see: look at 6
MainThread INFO process 7
Thread-7 INFO see: look at 7
MainThread INFO process 8
Thread-8 INFO see: look at 8
MainThread INFO process 9
MainThread INFO process 10
私がやっている唯一の奇妙なことは、セマフォが解放される場所以外のスレッドでセマフォ許可を取得することですが、セマフォはスレッドセーフであり、誰が許可を取得して解放するかについては気にしない必要があります。それぞれ同数。
確認日:
- Python 2.7.3 (Windows; python.org からビルド)
- Python 2.6.7 (Windows; cygwin dist)
- Python 2.6.6 (Linux; Debian ディストリビューション)
スレッドでデータを共有するにはどうすればよいですか?