なぜmath.factorialはスレッドでそれほど奇妙に動作するのですか?
次に例を示します。3つのスレッドを作成します。
- しばらく眠るだけのスレッド
- しばらくの間intをインクリメントするスレッド
- 多数でmath.factorialを実行するスレッド。
start
スレッドを呼び出しjoin
、タイムアウトします
start
スリープスレッドとスピンスレッドは期待どおりに機能し、すぐに戻ってからjoin
、タイムアウトのために待機します。
一方、階乗スレッドはstart
、最後まで実行されるまで戻りません。
import sys
from threading import Thread
from time import sleep, time
from math import factorial
# Helper class that stores a start time to compare to
class timed_thread(Thread):
def __init__(self, time_start):
Thread.__init__(self)
self.time_start = time_start
# Thread that just executes sleep()
class sleep_thread(timed_thread):
def run(self):
sleep(15)
print "st DONE:\t%f" % (time() - time_start)
# Thread that increments a number for a while
class spin_thread(timed_thread):
def run(self):
x = 1
while x < 120000000:
x += 1
print "sp DONE:\t%f" % (time() - time_start)
# Thread that calls math.factorial with a large number
class factorial_thread(timed_thread):
def run(self):
factorial(50000)
print "ft DONE:\t%f" % (time() - time_start)
# the tests
print
print "sleep_thread test"
time_start = time()
st = sleep_thread(time_start)
st.start()
print "st.start:\t%f" % (time() - time_start)
st.join(2)
print "st.join:\t%f" % (time() - time_start)
print "sleep alive:\t%r" % st.isAlive()
print
print "spin_thread test"
time_start = time()
sp = spin_thread(time_start)
sp.start()
print "sp.start:\t%f" % (time() - time_start)
sp.join(2)
print "sp.join:\t%f" % (time() - time_start)
print "sp alive:\t%r" % sp.isAlive()
print
print "factorial_thread test"
time_start = time()
ft = factorial_thread(time_start)
ft.start()
print "ft.start:\t%f" % (time() - time_start)
ft.join(2)
print "ft.join:\t%f" % (time() - time_start)
print "ft alive:\t%r" % ft.isAlive()
そして、CentOSx64でのPython2.6.5の出力は次のとおりです。
sleep_thread test
st.start: 0.000675
st.join: 2.006963
sleep alive: True
spin_thread test
sp.start: 0.000595
sp.join: 2.010066
sp alive: True
factorial_thread test
ft DONE: 4.475453
ft.start: 4.475589
ft.join: 4.475615
ft alive: False
st DONE: 10.994519
sp DONE: 12.054668
CentOSx64のpython2.6.5、Windows x86の2.7.2でこれを試しましたが、スレッドの実行が完了するまで、どちらの場合も階乗スレッドは最初から戻りません。
Windowsx86のPyPy1.8.0でもこれを試しましたが、結果が少し異なります。スタートはすぐに戻りますが、その後、参加はタイムアウトしません!
sleep_thread test
st.start: 0.001000
st.join: 2.001000
sleep alive: True
spin_thread test
sp.start: 0.000000
sp DONE: 0.197000
sp.join: 0.236000
sp alive: False
factorial_thread test
ft.start: 0.032000
ft DONE: 9.011000
ft.join: 9.012000
ft alive: False
st DONE: 12.763000
IronPython 2.7.1も試してみましたが、期待どおりの結果が得られます。
sleep_thread test
st.start: 0.023003
st.join: 2.028122
sleep alive: True
spin_thread test
sp.start: 0.003014
sp.join: 2.003128
sp alive: True
factorial_thread test
ft.start: 0.002991
ft.join: 2.004105
ft alive: True
ft DONE: 5.199295
sp DONE: 5.734322
st DONE: 10.998619