{"id":100,"date":"2025-10-25T07:09:41","date_gmt":"2025-10-25T07:09:41","guid":{"rendered":"https:\/\/codetypingpro.com\/?p=100"},"modified":"2025-12-17T07:49:36","modified_gmt":"2025-12-17T07:49:36","slug":"lesson-26-multithreading-and-multiprocessing-in-python","status":"publish","type":"post","link":"https:\/\/codetypingpro.com\/?p=100","title":{"rendered":"Lesson 26: Multithreading and Multiprocessing in Python"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\"><\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfaf <strong>Lesson Objective<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To understand how to execute multiple tasks <strong>concurrently<\/strong> or <strong>in parallel<\/strong> in Python, using <strong>threads<\/strong> and <strong>processes<\/strong>.<br>You\u2019ll learn the difference between <strong>multithreading<\/strong> and <strong>multiprocessing<\/strong>, when to use each, and how to build efficient, scalable programs.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\udde9 <strong>1. What Are Threads and Processes?<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Concept<\/th><th>Description<\/th><th>Example<\/th><\/tr><\/thead><tbody><tr><td><strong>Thread<\/strong><\/td><td>A lightweight unit of a process that shares the same memory space.<\/td><td>Running background tasks like updating UI or downloading files.<\/td><\/tr><tr><td><strong>Process<\/strong><\/td><td>An independent program with its own memory and resources.<\/td><td>Running multiple Python scripts at once or CPU-heavy tasks.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>In simple terms:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Threading<\/strong> = Multiple tasks <strong>sharing the same memory<\/strong> (good for I\/O tasks)<\/li>\n\n\n\n<li><strong>Multiprocessing<\/strong> = Multiple Python <strong>instances<\/strong> (good for CPU-heavy tasks)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\udde0 <strong>2. Why Use Concurrency?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When your program performs multiple tasks such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Downloading files from the internet<\/li>\n\n\n\n<li>Reading and writing files<\/li>\n\n\n\n<li>Performing data analysis on large datasets<\/li>\n\n\n\n<li>Handling multiple client requests on a server<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">you don\u2019t want one task to block others.<br>That\u2019s where <strong>multithreading<\/strong> and <strong>multiprocessing<\/strong> help by running tasks concurrently.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2699\ufe0f <strong>3. The Global Interpreter Lock (GIL)<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Python\u2019s <strong>GIL (Global Interpreter Lock)<\/strong> allows only one thread to execute Python bytecode at a time within a single process.<br>This means:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Multithreading in Python doesn\u2019t achieve <em>true<\/em> parallelism for CPU-bound tasks.<\/li>\n\n\n\n<li>But it\u2019s perfect for <strong>I\/O-bound tasks<\/strong>, like waiting for network responses or reading from files.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">For <strong>CPU-bound<\/strong> tasks (e.g., complex calculations), use <strong>multiprocessing<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\uddf5 <strong>4. Multithreading in Python<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Importing the Module<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>import threading\nimport time\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Example 1 \u2014 Basic Multithreading<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>def print_numbers():\n    for i in range(5):\n        print(f\"Number: {i}\")\n        time.sleep(1)\n\ndef print_letters():\n    for ch in \"ABCDE\":\n        print(f\"Letter: {ch}\")\n        time.sleep(1)\n\nt1 = threading.Thread(target=print_numbers)\nt2 = threading.Thread(target=print_letters)\n\nt1.start()\nt2.start()\n\nt1.join()\nt2.join()\n\nprint(\"Both threads completed.\")\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83e\uddfe <strong>Output:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Number: 0\nLetter: A\nNumber: 1\nLetter: B\n...\nBoth threads completed.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u2705 Both tasks run <em>concurrently<\/em>, sharing the same CPU core.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Example 2 \u2014 Threads with Arguments<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>def greet(name):\n    print(f\"Hello, {name}!\")\n    time.sleep(2)\n    print(f\"Goodbye, {name}!\")\n\nthread1 = threading.Thread(target=greet, args=(\"Sameer\",))\nthread2 = threading.Thread(target=greet, args=(\"Ali\",))\n\nthread1.start()\nthread2.start()\nthread1.join()\nthread2.join()\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83e\uddfe <strong>Output (interleaved):<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Hello, Sameer!\nHello, Ali!\nGoodbye, Sameer!\nGoodbye, Ali!\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\">Example 3 \u2014 Thread Synchronization (Lock)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">When multiple threads access shared data, race conditions can occur. Use a <strong>Lock<\/strong> to prevent this.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>lock = threading.Lock()\nshared_counter = 0\n\ndef increment():\n    global shared_counter\n    for _ in range(100000):\n        with lock:\n            shared_counter += 1\n\nthreads = &#91;threading.Thread(target=increment) for _ in range(5)]\n\nfor t in threads: t.start()\nfor t in threads: t.join()\n\nprint(\"Final counter:\", shared_counter)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u2705 Without the lock, the result would be unpredictable.<br>\u2705 With the lock, <code>shared_counter<\/code> becomes exactly <code>500000<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd04 <strong>5. Multiprocessing in Python<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Importing the Module<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>from multiprocessing import Process\nimport os, time\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Example 1 \u2014 Basic Multiprocessing<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>def worker(task_id):\n    print(f\"Task {task_id} running on process {os.getpid()}\")\n    time.sleep(2)\n    print(f\"Task {task_id} completed\")\n\nif __name__ == \"__main__\":\n    processes = &#91;]\n    for i in range(4):\n        p = Process(target=worker, args=(i,))\n        processes.append(p)\n        p.start()\n\n    for p in processes:\n        p.join()\n\n    print(\"All processes finished.\")\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83e\uddfe <strong>Output:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Task 0 running on process 23456\nTask 1 running on process 23457\n...\nAll processes finished.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u2705 Each task runs in <strong>its own process<\/strong>, truly in parallel on multiple CPU cores.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Example 2 \u2014 Using a Process Pool<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>multiprocessing.Pool<\/code> class helps manage multiple processes efficiently.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from multiprocessing import Pool\nimport time\n\ndef square(n):\n    time.sleep(1)\n    return n * n\n\nif __name__ == \"__main__\":\n    numbers = &#91;1, 2, 3, 4, 5]\n    with Pool(processes=3) as pool:\n        results = pool.map(square, numbers)\n    print(\"Squares:\", results)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83e\uddfe <strong>Output:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Squares: &#91;1, 4, 9, 16, 25]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u2705 Tasks are distributed among 3 worker processes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\">Example 3 \u2014 Sharing Data Between Processes<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>from multiprocessing import Value, Lock, Process\n\ndef add(lock, counter):\n    for _ in range(1000):\n        with lock:\n            counter.value += 1\n\nif __name__ == \"__main__\":\n    lock = Lock()\n    counter = Value('i', 0)\n    processes = &#91;Process(target=add, args=(lock, counter)) for _ in range(5)]\n\n    for p in processes: p.start()\n    for p in processes: p.join()\n\n    print(\"Final Counter:\", counter.value)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u2705 Uses shared memory variable (<code>Value<\/code>) and a <code>Lock<\/code> to synchronize updates.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u26a1 <strong>6. Comparing Threading vs. Multiprocessing<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Feature<\/th><th>Multithreading<\/th><th>Multiprocessing<\/th><\/tr><\/thead><tbody><tr><td><strong>Type of Task<\/strong><\/td><td>I\/O-bound<\/td><td>CPU-bound<\/td><\/tr><tr><td><strong>Execution Model<\/strong><\/td><td>Concurrent<\/td><td>Parallel<\/td><\/tr><tr><td><strong>Memory<\/strong><\/td><td>Shared memory space<\/td><td>Separate memory for each process<\/td><\/tr><tr><td><strong>Overhead<\/strong><\/td><td>Low<\/td><td>High<\/td><\/tr><tr><td><strong>Performance<\/strong><\/td><td>Limited by GIL<\/td><td>True multi-core utilization<\/td><\/tr><tr><td><strong>Example<\/strong><\/td><td>File downloads, web requests<\/td><td>Image processing, math computations<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\udde0 <strong>7. Example \u2014 File Download Automation (Multithreading)<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>import threading, requests, time\n\nurls = &#91;\n    \"https:\/\/example.com\/file1.jpg\",\n    \"https:\/\/example.com\/file2.jpg\",\n    \"https:\/\/example.com\/file3.jpg\"\n]\n\ndef download_file(url):\n    print(f\"Downloading {url}\")\n    response = requests.get(url)\n    filename = url.split(\"\/\")&#91;-1]\n    with open(filename, \"wb\") as f:\n        f.write(response.content)\n    print(f\"Completed: {filename}\")\n\nstart = time.time()\nthreads = &#91;threading.Thread(target=download_file, args=(url,)) for url in urls]\n\nfor t in threads: t.start()\nfor t in threads: t.join()\n\nprint(\"All downloads finished in\", round(time.time() - start, 2), \"seconds\")\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u2705 Multiple files download <strong>concurrently<\/strong>, saving significant time.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\uddee <strong>8. Example \u2014 Parallel Image Resizing (Multiprocessing)<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>from multiprocessing import Pool\nfrom PIL import Image\nimport os\n\ndef resize_image(filename):\n    img = Image.open(filename)\n    img = img.resize((300, 300))\n    img.save(f\"resized_{filename}\")\n    return filename\n\nif __name__ == \"__main__\":\n    images = &#91;f for f in os.listdir() if f.endswith(\".jpg\")]\n    with Pool(processes=4) as pool:\n        pool.map(resize_image, images)\n    print(\"All images resized.\")\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u2705 Each image is processed in parallel across 4 CPU cores.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\uddea <strong>9. Practical Use Cases<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Use Case<\/th><th>Technique<\/th><th>Example<\/th><\/tr><\/thead><tbody><tr><td>Web scraping multiple pages<\/td><td>Threading<\/td><td>Use <code>requests<\/code> + <code>threading<\/code><\/td><\/tr><tr><td>Large data computation<\/td><td>Multiprocessing<\/td><td>Use <code>Pool.map()<\/code><\/td><\/tr><tr><td>File backup &amp; organization<\/td><td>Threading<\/td><td>Handle multiple file operations<\/td><\/tr><tr><td>Video rendering<\/td><td>Multiprocessing<\/td><td>Use all CPU cores<\/td><\/tr><tr><td>Server handling multiple clients<\/td><td>Threading<\/td><td>Each client connection in a thread<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udca1 <strong>10. Key Tips<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <strong>threading<\/strong> when your tasks are mostly waiting (I\/O-bound).<\/li>\n\n\n\n<li>Use <strong>multiprocessing<\/strong> for computation-heavy tasks.<\/li>\n\n\n\n<li>Always use <code>.join()<\/code> to ensure threads\/processes finish before the program exits.<\/li>\n\n\n\n<li>Avoid shared mutable data between threads unless you use locks or queues.<\/li>\n\n\n\n<li>Use <code>concurrent.futures<\/code> for a simpler API: <code>from concurrent.futures import ThreadPoolExecutor<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><\/h2>\n","protected":false},"excerpt":{"rendered":"<p>\ud83c\udfaf Lesson Objective To understand how to execute multiple tasks concurrently or in parallel in Python, using threads and processes.You\u2019ll learn the difference between multithreading and multiprocessing, when to use each, and how to build efficient, scalable programs. \ud83e\udde9 1. What Are Threads and Processes? Concept Description Example Thread A lightweight unit of a process [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,1],"tags":[],"class_list":["post-100","post","type-post","status-publish","format-standard","hentry","category-python-easy-course-outline","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/posts\/100","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=100"}],"version-history":[{"count":1,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/posts\/100\/revisions"}],"predecessor-version":[{"id":101,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/posts\/100\/revisions\/101"}],"wp:attachment":[{"href":"https:\/\/codetypingpro.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=100"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=100"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=100"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}