OS Lab - 1 HANDOUT
OS Lab - 1 HANDOUT
Mehrdad Ahmadzadeh
Is Prime?
Is Prime?
Is Prime?
02-example2.py
While there was no actual concurrency involved in the second
method, the overhead cost of spawning new threads
contributed to the significantly worse execution time.
This is one example of inherently sequential tasks, where
concurrency or parallelism should not be applied to attempt
an improvement in execution time.
Concurrency in Python
Concurrency in Python can be achieved through several
mechanisms, each with its own characteristics and use cases.
Multithreading
Multiprocessing
Asyncio
Concurrent Futures
Multithreading
Python provides the threading module, which allows you to
run multiple threads (smaller units of a process) concurrently.
However, due to the Global Interpreter Lock (GIL), Python
threads are not truly parallel; they are useful for I/O-bound
tasks where threads spend a lot of time waiting for external
events (like network responses or file I/O).
Multithreading
Multiprocessing
The multiprocessing module allows the creation of separate
processes, each with its own Python interpreter and memory
space. This is effective for CPU-bound tasks since it bypasses
the GIL and allows for true parallelism.
Multiprocessing
Asyncio
The asyncio module provides a framework for writing
single-threaded concurrent code using coroutines. It is
particularly well-suited for I/O-bound tasks and allows you to
manage a large number of connections simultaneously with an
event loop.
Asyncio
Concurrent Futures
The concurrent.futures module provides a high-level interface
for asynchronously executing callables. It abstracts the use of
threads and processes and allows you to submit tasks and
retrieve their results.
Concurrent Futures
Concurrent Futures
_ = ...: The underscore (_) is a common convention in
Python to indicate that the result of the expression is not
going to be used. In this case, the program is effectively
ignoring the actual futures returned by as_completed.
However, this line ensures that the main thread will wait for
all submitted tasks to finish before moving on.
Concurrent Futures
Concurrent Futures
CPU while running the code:
Thread Class
To use threads you need import Thread using the following
code: from threading import Thread
To create a thread in Python you’ll want to make your class
work as a thread. For this, you should subclass your class
from the Thread class
Threads
04-helloPythonWithThreads.py
Threads
04-helloPythonWithThreads.py
Threads
04-helloPythonWithThreads.py
Threads
When using threads you must always make sure that you
never leave any thread running in the background.
This is very bad programming and can cause you all sorts of
pain when you work on bigger applications.
Multithreading
The most widely used programming paradigm for the
management of concurrence in software applications is based
on multithreading.
Generally, an application is made by a single process that is
divided into multiple independent threads, which represent
activities of different types that run parallel and compete with
each other.
Multithreading
All the existing operating systems support multithreading
In almost all programming languages, there are mechanisms
that you can use to implement concurrent applications
through the use of threads.
Multithreaded programming is a good choice to achieve
concurrent applications.
Multithreading
Shared resources
data
operating system resources
States of execution
ready
running
blocked
Define a thread
The simplest way to use a thread is to instantiate it with a
target function and then call the start() method
class threading.Thread(group=None,
target=None,
name=None,
args=(),
kwargs={})
Define a thread
group: This is the value of group that should be None; this is
reserved for future implementations
target: This is the function that is to be executed when you
start a thread activity
name: This is the name of the thread; by default, a unique
name of the form Thread-N is assigned to it
args: This is the tuple of arguments that are to be passed to
a target
kwargs: This is the dictionary of keyword arguments that are
to be used for the target function
The thread does not start running until the start() method is
called
The method join() blocks the calling thread until the thread
whose join() method is called is terminated.
Mehrdad Ahmadzadeh OS-Lab 1
Thread-based Parallelism
Define a thread
06-Thread_definition.py
Lock VS RLock
The default Lock doesn’t recognize which thread the lock
currently holds.
If the shared resource is being accessed by any thread then
other threads trying to access the shared resource will get
blocked even if it is the same thread that locked the shared
resource.
If a shared resource is in RLock then it can be called again
safely.
Lock Example
13-lock.py
Lock VS RLock
Please refer to 13-Rlock_2 and 13-Rlock_3 .py for more details.
Deadlock
Using lock can often lead the execution to a bad situation of
deadlock.
A deadlock occurs due to the acquisition of a lock from
different threads
It is impossible to proceed with the execution of operations
since the various locks between them block access to the
resources.
.
Deadlock
Monitors
Monitors in the context of concurrent programming are
essentially a higher-level abstraction that combines locking
and condition variables to manage access to shared resources.