This document provides an overview of multithreading in C++11, detailing how to create threads, manage thread execution, and handle common issues like race conditions. It explains the use of mutexes for data protection and introduces standard library classes like std::lock_guard and std::unique_lock for managing thread locks. Additionally, it discusses asynchronous communication between threads using std::promise and std::future.
Overview of programming training with Sikander, covering C, Modern C++, Python, and Linux System Programming.
Introduces multithreading in C++11, creating threads using std::thread, and waiting for threads to finish with join().
Details on thread creation, differentiating threads, and compares function calls to thread execution.
Discusses passing arguments to threads, focusing on multiple arguments and passing by reference.
Starting threads with member functions and explores outputs of thread execution in various scenarios. Describes race conditions in multithreading where shared data access causes unexpected results.
Introduces mutex as a solution for race conditions, detailing locking and unlocking mechanisms.
Explains the importance of unlocking mutexes and introduces std::lock_guard for managing mutexes.
Describes std::lock_guard class for automatic mutex management to prevent locking issues.
Explains std::unique_lock for managing mutexes with unique ownership for improved thread safety.
Introduces futures and promises for asynchronous thread communication and value retrieval.
Wraps up the presentation and thanks the audience.
Programming with Sikander
CorporateTrainer: C, Modern C++, Python, Linux System Prog
YouTube :
https://www.youtube.com/playlist?list=PLXfErIZsDibZTMKS-istzXHTTlbS0U37O
1
2.
Multithreading
Original C++ Standardsupported only
single thread programming.
The new C++ Standard, C++11, a new
thread library is introduced.
In every C++ application there is one
default main thread i.e. main() function.
We can create additional threads by
creating objects of std::thread class.
Each of the std::thread object can be
associated with a thread.
Programming with Sikander : Modern C++: Multithreading 2
3.
Thread Creation
To starta thread we simply need to create
a new thread object and pass the
executing code to be called (i.e, a callable
object) into the constructor of the object.
Once the object is created a new thread is
launched which will execute the code
specified in callable.
The callable can be
▪ Address of function / Lambda Expression
▪ Function Object (Member Function)
Programming with Sikander : Modern C++: Multithreading 3
4.
Waiting for threadsto finish
Once a thread has started we may need to wait
for the thread to finish before we can take some
action.
To wait for a thread use the std::thread::join()
function.
This function makes the current thread wait until
the thread identified by *this has finished
executing.
Programming with Sikander : Modern C++: Multithreading 4
5.
Thread creation –Global Function
Programming with Sikander : Modern C++: Multithreading 5
6.
If a threadobject is not initialized, it can
be assigned at a later stage.
Programming with Sikander : Modern C++: Multithreading 6
7.
Differentiating between threads
Everyrunning thread has an id.
Thread id can be obtained using get_id
method.
To refer to current thread: this_thread.
Every process starts a new thread
generally referred as the main thread.
Programming with Sikander : Modern C++: Multithreading 7
Two threads runningon same
function
Programming with Sikander : Modern C++: Multithreading 14
15.
What is theoutput?
Programming with Sikander : Modern C++: Multithreading 15
16.
What is theoutput?
Programming with Sikander : Modern C++: Multithreading 16
17.
Passing argument byreference
Programming with Sikander : Modern C++: Multithreading 17
18.
Starting a Threadwith a Member
Function
◼ Starting a thread with a member function
of a class requires special attention.
Programming with Sikander : Modern C++: Multithreading 18
◼ Thread Initialization
Data Sharing andRace Conditions
In multithreading environment data sharing
between threads is very easy.
But this easy sharing of data can cause
problems in application.
One such problem is Race Condition.
Programming with Sikander : Modern C++: Multithreading 20
21.
What is theoutput?
Programming with Sikander : Modern C++: Multithreading 21
22.
What is theoutput?
Programming with Sikander : Modern C++: Multithreading 22
23.
Race Condition
When twoor more threads perform a set of
operations in parallel, that access the same
memory location.
Also, one or more thread out of them modifies
the data in that memory location, then this can
lead to an unexpected results some times.
This is called race condition.
Race conditions are usually hard to find because
they don’t occur every time.
They will occur only when relative order of
execution of operations by two or more threads
leads to an unexpected result.
Programming with Sikander : Modern C++: Multithreading 23
Fixing Race Condition
•To fix race conditions in multi-threaded
environment we need mutex.
• Each thread needs to lock a mutex before
modifying or reading the shared data and after
modifying the data each thread should unlock the
mutex.
• The mutexes are in the <mutex> header file.
• The class representing a mutex is the std::mutex
class.
• There are two important methods of mutex:
1.) lock()
2.) unlock() Programming with Sikander : Modern C++: Multithreading 25
26.
Mutex
A mutex isa lockable object that is
designed to signal when critical sections
of code need exclusive access, preventing
other threads with the same protection
from executing concurrently and access
the same memory locations.
Programming with Sikander : Modern C++: Multithreading 26
std::lock_guard
• A C++Standard Library class for automatic locking
and unlocking of mutexes.
• Simple ownership model: Lock acquired on
construction, released on destruction
Example:
#include <mutex>
std::mutex myMutex;
std::lock_guard<std::mutex> lock(myMutex);
// ... critical section ...
// lock automatically released upon scope exit
Programming with Sikander : Modern C++: Multithreading 31
32.
std::lock_guard
lock_guard wraps themutex inside it’s object
and locks the attached mutex in its constructor.
When it’s destructor is called it releases the
mutex.
In this way, it guarantees the mutex object is
properly unlocked in case an exception is
thrown.
Programming with Sikander : Modern C++: Multithreading 32
• Advantages:
• Straightforwardusage.
• Minimal code for basic locking scenarios.
• Limitations:
• Lack of advanced features like deferred
locking.
Programming with Sikander : Modern C++: Multithreading 34
std::lock_guard
35.
Std::unique_lock
A unique lockis an object that manages
a mutex object with unique ownership.
On construction, the object acquires
a mutex object, for whose locking and
unlocking operations becomes responsible.
The object supports both states: locked and
unlocked.
This class guarantees an unlocked status on
destruction (even if not called explicitly).
Programming with Sikander : Modern C++: Multithreading 35
Future
Futures are ahigh level mechanism for
passing a value between threads, and
allow a thread to wait for a result to be
available without having to manage the
locks directly.
One use of a future is to hold the result of
a call to the new async function for
running some code asynchronously
Programming with Sikander : Modern C++: Multithreading 37
std::promise
◼ std::promise isa C++ Standard Library class
that provides a simple mechanism for
asynchronous communication between
threads.
◼ A std::promise object represents a promise
for a value that will be made available in the
future.
◼ It is typically used in conjunction with a
std::future object, which is used to retrieve
the value at a later point in the program's
execution.
Programming with Sikander : Modern C++: Multithreading 40