Python's Global Interpreter Lock (GIL) is a mutex that protects access to Python objects, preventing multiple threads from executing Python bytecode simultaneously. This has a surprising consequence: for CPU-bound tasks, multithreading in Python does not provide parallel speedup.
Your task is to implement two functions that demonstrate this behavior:
factorial(n: int) -> int — computes n! recursively. Base case: factorial(0) = 1.multi_thread_factorial(n: int) -> tuple[Thread, Thread] — returns a tuple of two Thread objects, each targeting factorial with n as the argument. Do not start the threads — just create and return them.The harness will start and join the threads, measure wall-clock time, and compare against a single-threaded baseline.
Constraints:
0 <= n <= 500multi_thread_factorialmultiprocessing, concurrent.futures, or any non-threading concurrency primitivefactorial with the same n