Multithreading vs. Multiprocessing: Understanding the Differences