Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7670981
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 31, 20262026-05-31T15:56:41+00:00 2026-05-31T15:56:41+00:00

Why does math.factorial act so weird in a thread? Here is an example, it

  • 0

Why does math.factorial act so weird in a thread?

Here is an example, it creates three threads:

  • thread that just sleeps for a while
  • thread that increments an int for a while
  • thread that does math.factorial on a large number.

It calls start on the threads, then join with a timeout

The sleep and spin threads work as expected and return from start right away, and then sit in the join for the timeout.

The factorial thread on the other hand does not return from start until it runs to the end!

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()

And here is the output on Python 2.6.5 on CentOS x64:

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

I’ve tried this on python 2.6.5 on CentOS x64, 2.7.2 on Windows x86 and the factorial thread does not return from start on either of them until the thread is done executing.

I’ve also tried this with PyPy 1.8.0 on Windows x86, and there result is slightly different. The start does return immediately, but then the join doesn’t time out!

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

Tried IronPython 2.7.1 too, it produces the expected result.

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
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-31T15:56:43+00:00Added an answer on May 31, 2026 at 3:56 pm

    Threads often only allow different things to be interleaved in Python, not different things to happen at the same time, because of the Global Interpreter Lock.

    If you look at the Python bytecode:

    from math import factorial
    
    def fac_test(x):
        factorial(x)
    
    import dis
    dis.dis(fac_test)
    

    you get:

      4           0 LOAD_GLOBAL              0 (factorial)
                  3 LOAD_FAST                0 (x)
                  6 CALL_FUNCTION            1
                  9 POP_TOP             
                 10 LOAD_CONST               0 (None)
                 13 RETURN_VALUE        
    

    As you can see, the call to math.factorial is a single operation at the Python bytecode level (6 CALL_FUNCTION) — it’s implemented in C. factorial doesn’t release the GIL because of the type of work it does (see the comments on my answer), so Python doesn’t switch to other threads while it’s running, and you get the result you’ve observed.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Why does the following code: Console.WriteLine(String.Format({0:C0}, 2170/ 20)); yield $109, while doing Console.WriteLine(Math.Round(2170 /
Does decimal math use the FPU? I would think that the answer is yes,
I am looking for a library that does advanced math, statistics, statistical distribution, etc..
I'm looking for a good Math library in objective-c that does your usual Matrix
I've written this very badly optimized C code that does a simple math calculation:
does anyone know of a Math method that returns the largest number of a
Why does ((255<<24)|(255<<16)|(255<<8)|255)>>>0 equals 4294967295 when Math.pow(256,4) equals 4294967296? Notice that the bitwise operation
What causes could there be, that gcc does not link to math.h even though
Does anybody have experience programming for both the Intel Math Kernel Library and the
What does the following expression return in Java? Math.max(Float.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); I saw this question

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.