0% found this document useful (0 votes)
4 views

multithreading

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

multithreading

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

Multithreading

1-Python Multithreading:

Multithreading is a threading technique in Python programming to run multiple threads concurrently by


rapidly switching between threads with a CPU help (called context switching). Besides, it allows sharing
of its data space with the main threads inside a process that share information and communication
with other threads easier than individual processes. Multithreading aims to perform multiple tasks
simultaneously, which increases performance, speed and improves the rendering of the application.

Benefits of Multithreading in Python

A thread is the smallest unit of a program or process executed independently or scheduled by the
Operating System. In the computer system, an Operating System achieves multitasking by dividing the
process into threads. A thread is a lightweight process that ensures the execution of the process
separately on the system. In Python 3, when multiple processors are running on a program, each
processor runs simultaneously to execute its tasks separately.

Following are the benefits to create a multithreaded application in Python, as follows:

1. It ensures effective utilization of computer system resources.

2. Multithreaded applications are more responsive.

3. It shares resources and its state with sub-threads (child) which makes it more economical.

4. It makes the multiprocessor architecture more effective due to similarity.

5. It saves time by executing multiple threads at the same time.

6. The system does not require too much memory to store multiple threads.

When to use Multithreading in Python?

It is a very useful technique for time-saving and improving the performance of an application.
Multithreading allows the programmer to divide application tasks into sub-tasks and simultaneously
run them in a program. It allows threads to communicate and share resources such as files, data, and
memory to the same processor. Furthermore, it increases the user's responsiveness to continue
running a program even if a part of the application is the length or blocked.

2- Threads and processes:

In Python, threads and processes are two different approaches for achieving parallelism, and they are
used based on different requirements. Let's break them down:

1. Threads:

Definition: A thread is a smaller unit of a process that can run concurrently. Multiple threads can exist
within the same process and share the same memory space.

Module: The threading module in Python provides support for working with threads.
Use Case: Threads are suitable when you need to perform I/O-bound tasks, like reading/writing files or
network operations, as Python's Global Interpreter Lock (GIL) restricts CPU-bound tasks from truly
running in parallel in the same process.

Key Features:

Shared memory space: Threads can communicate and share data easily.

Lightweight compared to processes.

Python threads are limited by the GIL, so only one thread executes Python bytecode at a time (in Python),
even on multi-core systems.

2. Processes:

Definition: A process is an independent entity that has its own memory space. Unlike threads,
processes do not share the same memory space.

Module: The multiprocessing module in Python provides support for spawning processes.

Use Case: Processes are used when you want to achieve true parallelism for CPU-bound tasks (like
heavy computations), because each process gets its own Python interpreter and memory space, and
is not affected by the GIL.

Key Features:

Separate memory space: Processes do not share memory by default (inter-process communication
can be achieved with pipes, queues, etc.).

Heavy compared to threads due to memory and CPU overhead.

True parallelism since processes are independent and not restricted by the GIL.

Key Differences Between Threads and Processes:

Memory: Threads share the same memory, whereas processes have separate memory.

GIL: Python's GIL affects threads, limiting their ability to execute concurrently for CPU-bound tasks.
Processes are not affected by the GIL.

Overhead: Threads are lightweight and faster to create, but processes are heavier due to the need for
separate memory space.

Communication: Threads can communicate directly through shared variables, but processes need
explicit mechanisms (like queues, pipes) for communication.

In summary:

Use threads when your task is I/O-bound (e.g., reading files or making network requests).

Use processes for CPU-bound tasks to bypass the GIL and achieve true parallelism.
3-How to achieve multithreading in Python?

There are two main modules of multithreading used to handle threads in Python.

3.1- The thread module

3.2-The threading module

3.1-Thread modules - A thread is an entity within a process that can be scheduled for execution. Also,
it is the smallest unit of processing that can be performed in an OS (Operating System). In simple words,
a thread is a sequence of such instructions within a program that can be executed independently of
other codes.

It is started with Python 3, designated as obsolete, and can only be accessed with _thread that supports
backward compatibility.

Syntax:

thread.start_new_thread ( function_name, args[, kwargs] )

example:

import _thread import time def name(n):

time.sleep(0.5) print("my name is:",n)

def country(m):

time.sleep(0.5)

print("my country is :",m) r=time.time()

_thread.start_new_thread(name,("sai",))

_thread.start_new_thread(country,("india",))

print("time taken to execute two functions:",time.time()-r)

output:

my name is sai my country is india

time taken to execute two functions:00:0045555

Types of Threads

There are two types of threads, which are:

1. User Level Thread

As the name suggests, the user-level threads are only managed by users, and the kernel does not have
its information.

These are faster, easy to create and manage.


The kernel takes all these threads as a single process and handles them as one process only. The user-
level threads are implemented by user- level libraries, not by the system calls.

2. Kernel-Level Thread

The kernel-level threads are handled by the Operating system and managed by its kernel. These threads
are slower than user-level threads because context information is managed by the kernel. To create and
implement a kernel-level thread, we need to make a system call.

Features of Thread

• Threads share data, memory, resources, files, etc., with their peer threads within a process.

• One system call is capable of creating more than one thread.

• Each thread has its own stack and register.

• Threads can directly communicate with each other as they share the same address space.

• Threads need to be synchronized in order to avoid unexpected scenarios.

3.2-Threading Modules

The threading module included with Python 3.4 provides much more powerful, high-level support for
threads than the thread module .To use multithreading, we need to import the threading module in
Python Program.

The threading module exposes all the methods of the thread module and provides some additional
methods −

• threading.activeCount() − Returns the number of thread objects that are active.

• threading.currentThread() − Returns the number of thread objects in the caller's thread control.

• threading.enumerate() − Returns a list of all thread objects that are currently active.

In addition to the methods, the threading module has the Thread class that implements threading. The
methods provided by the Thread class are as follows −

• run() − The run() method is the entry point for a thread.

• start() − The start() method starts a thread by calling the run method.

• join() − The join() waits for threads to terminate.

• isAlive() − The isAlive() method checks whether a thread is still executing.

• getName() − The getName() method returns the name of a thread.

• setName() − The setName() method sets the name of a thread.


Threading Module Objects:

Apart from the functions specified above, the threading module also provides many classes whose
objects are very useful in creating and managing threads.

Following are some of the Object types:

Object Description

Thread Object that represents a single thread of execution.

Lock Primitive lock object.

RLock RLock or Re-entrant lock object provides ability for a single


thread to (re)acquire an already-held lock (recursive locking).

Condition Condition variable object causes one thread to wait until


certain "condition" has been satisfied by another thread (such
as change in state or some data value)

Event Its a more general version of condition variables, whereby a


number of threads can be made to wait for some event to occur
and all the threads waiting will only awaken when the event
happens.

Semaphore Provides a "counter" of finite resources shared between


threads block when none are available.

Bounded Semaphore Similar to a Semaphore but ensures that it never exceeds its
initial value.
Timer Similar to Thread, except that it waits for a specified period
of time before running.
Barrier Creates a "barrier" at which a specified number of threads
must all arrive before they're all allowed to continue.

Python Global Interpreter Lock (GIL)

A global interpreter lock (GIL) is a mechanism to apply a global lock on an interpreter. It is used in
computer-language interpreters to synchronize and manage the execution of threads so that only one
native thread (scheduled by the operating system) can execute at a time.

In a scenario where you have multiple threads, what can happen is that both the thread might try to
acquire the memory at the same time, and as a result of which they would overwrite the data in the
memory. Hence, arises a need to have a mechanism that could help prevent this phenomenon.

Some popular interpreters that have GIL are CPython and Ruby MRI. As most of you would know that
Python is an interpreted language, it has various distributions like CPython, Jython, IronPython. Out of
these, GIL is supported only in CPython, and it is also the most widely used implementation of Python.
CPython has been developed in both C and Python language primarily to support and work with
applications that have a lot of C language underneath the hood.
Hence, GIL (Source: Understanding the Python GIL):

• Limits the threading operation.

• Parallel execution is restricted.

• The GIL ensures that only one thread runs in the interpreter at once.

• It helps in simplifying various low-level details like memory management.

The impact of the GIL isn’t visible to developers who execute single-threaded programs. Since the GIL
allows only one thread to execute at a time even in a multi- threaded architecture with more than one
CPU core, the GIL has gained a reputation as an “infamous” feature of Python.

Python Global Interpreter Lock (GIL) is a type of process lock which is used by python whenever it deals
with processes. Generally, Python only uses only one thread to execute the set of written statements.
This means that in python only one thread will be executed at a time. The performance of the single-
threaded process and the multi-threaded process will be the same in python and this is because of GIL
in python. We cannot achieve multithreading in python because we have global interpreter lock which
restricts the threads and works as a single thread.

You might also like