Introduction
In the realm of software development, concurrent execution refers to the ability of a program to perform multiple tasks simultaneously. This is achieved by breaking down tasks into smaller units of execution and running them concurrently, rather than sequentially.
Concurrency and parallelism are two concepts often discussed in the context of concurrent programming in Python.
Concurrency:
- Concurrency is the capability of a program to handle and execute multiple tasks simultaneously, potentially overlapping in time. It does not necessarily mean that tasks are executed simultaneously, but rather that the program manages multiple tasks in a way that gives the appearance of simultaneous execution. Concurrency is typically achieved using threading.
Parallelism:
- Parallelism is the concurrent execution of numerous tasks or processes, often across various processors. Unlike concurrency, where tasks may not genuinely occur simultaneously, parallelism guarantees that tasks are executed concurrently on distinct computational units. Parallelism can be achieved using multiprocessing.
Threading and multiprocessing:
Threading: Threading is a technique used to achieve concurrent execution within a single process. It involves dividing a program into multiple threads of execution, each capable of running independently.
Threads share the same memory space and resources within the process, allowing them to communicate and synchronize data easily.
Multiprocessing: Multiprocessing is running the multiple processes simultaneously, each with its own memory space and resources. Unlike threading, multiprocessing enables true parallelism by utilizing multiple CPU cores or processors. Processes are independent of each other and communicate through inter-process communication mechanisms.
Threading Example:
import threading
import time
def num():
for i in range(1, 11):
print(i)
time.sleep(1) #time-consuming operation
#creating a thread to execute
thread = threading.Thread(target=num)
thread.start()
thread.join()
print("Thread execution complete!")
First we import the
threading
module, which provides support for working with threads in Python. We also import thetime
module for time-related operations.We define a function
num()
that prints numbers from 1 to 10 using a for loop. Inside the loop, we print the current number and then calltime.sleep(1)
to simulate a time-consuming operation. This sleep pauses the execution of the thread for 1 second, simulating some work being done.We create a thread object
thread
usingthreading.Thread
, passing thetarget
parameter as thenum
function. This prepares the thread to execute thenum
function when started.We start the execution of the thread by calling
thread.start()
. This initiates the execution of thenum
function in a separate thread, allowing it to run concurrently with the main program.We use
thread.join()
to wait for the thread to finish its execution. This line pauses the main program's execution until thethread
has completed executing thenum
function.
After the thread has finished executing, we print "Thread execution complete!" to indicate that the thread has finished its task.
In summary, this code demonstrates the use of threading in Python to execute a function (print_numbers
) concurrently in a separate thread. The main program waits for the thread to finish its task before proceeding further.
Multiprocessing Example:
import multiprocessing
import time
def num():
for i in range(1, 11):
print(i)
time.sleep(1)
#creating a process
process = multiprocessing.Process(target=num)
process.start()
process.join()
print("Process execution complete!")
We import the
multiprocessing
module, which provides support for working with processes in Python.We define a function
num()
that prints numbers from 1 to 10 using a for loop.Just like above example , pauses the execution of process for 1 sec .
We create a process object
process
usingmultiprocessing.Process
, passing thetarget
parameter as thenum
function. This prepares the process to execute thenum
function when started.We start the execution of the process by calling
process.start()
. This initiates the execution of thenum
function in a separate process, allowing it to run concurrently with the main program.Using
process.join()
to wait for the process to finish its execution. This line pauses the main program's execution until theprocess
has completed executing thenum
function.After the process has finished executing, we print "Process execution complete!" to indicate that the process has finished its task.
Conclusion
In summary, threading allows multiple threads to run within a single process, while multiprocessing involves running multiple processes simultaneously. Multiprocessing is typically used for CPU-bound tasks that can benefit from parallel execution, such as numerical computations, data processing. Threading is commonly used for tasks that involve I/O operations or managing multiple tasks simultaneously without blocking the main program's execution.