Day #97 - Multithreading in Python

Day #97 - Multithreading in Python

ยท

4 min read

Introduction

Welcome to my 97th blog post on the Python journey. On day 97, I learned about a concept called Multithreading in Python that can be used to run multiple threads of execution concurrently within a single process. Let's dive into more details and understand the basics of multi-threading in Python.

So let's get started......

Multi-threading in Python

  • This allows multiple threads of execution to run concurrently within a single process.

  • Here the 'threading' module is used to implement multithreading.

Importing Threading Syntax

import threading

Creating a Thread

We create a 'Thread' object and then call its start() method. This start() method runs the thread and then to stop the thread execution, use the join() method.

Syntax -

import threading
def my_func():
  print("Hello from thread", threading.current_thread().name)
  thread = threading.Thread(target=my_func)
  thread.start()
  thread.join()

my_func()

Threading Functions

Below are the most commonly used threading functions in Python.

  • threading.Thread(target, args): This function creates a new thread that runs the target function with the specified arguments.

  • threading.Lock(): creates a lock that can be used to synchronize access to shared resources between threads.

Create Multiple Threads

Here we create a pool of worker threads and then assign tasks to them as needed. This gives us the advantage of multiple CPU cores and processing the tasks in parallel.

import threading

def thread_task(task):
    # Do some work here
    print("Task processed:", task)

if __name__ == '__main__':
    tasks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    threads = []
    for task in tasks:
        thread = threading.Thread(target=thread_task, args=(task,))
        threads.append(thread)
        thread.start()

    for thread in threads:
        thread.join()

Using a lock to synchronize access to shared resources

  • In Multithreading, locks can be used to synchronize access to shared resources among multiple threads.

  • A lock is an object that acts as a semaphore, allowing only one thread at a time to execute a critical section of code.

  • This lock is released when the thread finishes executing the critical section.

Example -

import threading

def increment(counter, lock):
    for i in range(10000):
        lock.acquire()
        counter += 1
        lock.release()

if __name__ == '__main__':
    counter = 0
    lock = threading.Lock()

    threads = []
    for i in range(2):
        thread = threading.Thread(target=increment, args=(counter, lock))
        threads.append(thread)
        thread.start()

    for thread in threads:
        thread.join()

    print("Counter value:", counter)

Example -

import threading
import time
from concurrent.futures import ThreadPoolExecutor

# Indicates some task being done
def func(seconds):
  print(f"Sleeping for {seconds} seconds")
  time.sleep(seconds)
  return seconds

def main():
  time1 = time.perf_counter()

  # Normal Code
  # func(4) 
  # func(2)
  # func(1)


  # Same code using Threads
  t1 = threading.Thread(target=func, args=[4])
  t2 = threading.Thread(target=func, args=[2])
  t3 = threading.Thread(target=func, args=[1])
  t1.start()
  t2.start()
  t3.start()

  t1.join()
  t2.join()
  t3.join()
  # Calculating Time 
  time2 = time.perf_counter()
  print(time2 - time1)


def poolingDemo():
  with ThreadPoolExecutor() as executor:
    # future1 = executor.submit(func, 3)
    # future2 = executor.submit(func, 2)
    # future3 = executor.submit(func, 4)
    # print(future1.result())
    # print(future2.result())
    # print(future3.result())
    l = [3, 5, 1, 2]
    results = executor.map(func, l)
    for result in results:
      print(result)


poolingDemo()

Resources Used

You can watch the video of Day#97 by clicking on the below link ๐Ÿ‘‡๐Ÿ‘‡๐Ÿ‘‡๐Ÿ‘‡๐Ÿ‘‡

Conclusion

Thanks, guys for going through this blog post. On day 97, I learned about Multithreading in Python and how it can be used to run multiple operations concurrently within a single process. Using Multithreading we can use resources efficiently. With multithreading, we can take advantage of multiple CPU cores and significantly improve the performance of your code.

Thank you if you read this post and have found this post useful. I hope you have joined me and are enjoying my magical journey of Python coding. This is it for Day #97

See you in the next one.....


About Me

Hey Guys, I am Chintan Jain from CodeWithJain. I am a trader and content creator. I am also passionate about tech and hence wanted to explore the field of tech. I always wanted to learn to code so I watched many tutorials but procrastinated practicing coding. To get into the habit of coding consistently I am starting to BLOG with HASHNODE on daily basis.

I will document my coding journey from scratch and share my daily learnings in a blog post on HASHNODE. I hope you all will enjoy my content and my coding journey.

So what are you waiting for, smash the FOLLOW and LIKE buttons and follow along my coding journey, a step to create more beautiful digital products and empower people.


ย