
Explore multithreading fundamentals, including thread creation, destruction, and race conditions. Learn synchronization with mutexes, condition variables, semaphores, and producer–consumer and dining philosophers problems.
Clarify that a process has at least one thread—the main thread—and that any thread can fork new threads, creating parent and child threads in a multithreaded program.
Join the Telegram group to engage with peers about part a of multithreading and thread synchronization using Pthreads.
Write and discuss a first multithreaded Hello World program using the provided source code, with GitHub access and download options, and explore several aspects of the multithreaded program.
Create a basic multithreaded hello world program using pthreads, showing how the main thread spawns a child with pthread_create, passing heap or static memory as input, and guarding thread lifetime.
Learn how a pthread executes a generic function with a void pointer, printing a string every second in an infinite loop, and how main thread pause affects the child thread.
This can be Interview Question.
Discover how main thread termination differs from child thread termination in pthreads. End the main thread with pthread_exit to keep child threads running; terminating a child ends only that thread.
Learn how threads share resources like memory, cpu, peripherals, and shared virtual address space, while each keeps its own stack and life cycle; main thread death may terminate the process.
This can be an Interview Question. Very important.
Explain how the kernel schedules threads, not processes, across multiple CPUs, treating threads as schedulable entities, and examine signals, race conditions, and basic scheduling policies.
Understand singularism, doing tasks one at a time with no pre-emption, illustrated by three well diggers, and compare it to concurrency and parallelism regarding progression and speed.
Map the well-digging analogy to the multithreading world by equating workers to threads, resources to cpu and memory, and transitions to context switching.
Interview Questions :
Different between Parallel Processing and Concurrency.
Difference between Multi-Tasking and Parallel Processing.
Explore how concurrency enables multithreaded design when input/output waits occur alongside ongoing work, illustrated by a network application with threads for packet arrival, periodic sending, and user input.
Design a multithreaded tcp server by delegating each client to its own worker thread, isolating communication and enabling parallel handling of multiple independent connections.
Threads are lightweight processes because they reuse the main thread’s resources—page tables, shared libraries, and sockets—avoiding re-creation; resources remain for other threads, so thread switching is faster.
Identify overlapping and non-overlapping work between threads accessing the same data structure, using examples like array sorts, to decide if synchronization is required before applying mutexes or condition variables.
Explain joinable and detached threads in Pthreads, including how a parent thread joins a child, blocks at join, releases resources after join, and that the default is joinable with conversion.
Learn how detached threads release resources automatically after termination, without join operations, while joinable threads require joining; they can be converted to joinable during execution; includes a demo.
Explain that any thread can wait for any other joinable thread with pthread_join, as parent, child, and grandchild illustrate join points and the rule against joining detached threads.
Learn the mapreduce paradigm by splitting a large text into ranges, assigning them to mapper threads, and using a reducer that joins results to output the final word count.
Choose joinable threads when a thread returns a result or others must be notified of termination; use detached threads for infinite loops or waiting for input, like TCP servers.
Explore the difference between transfer of data and transfer of computation, contrasting sending data across entities with sending a function pointer within the same process to perform computation.
Discover notification chains as an architectural design pattern for notifying multiple subscribers about publisher events, where publishers emit events that subscribers register to receive across threads, processes, or components.
Understand the publisher–subscriber model and notification chains, where subscribers register with keys or wildcards and publishers invoke callbacks on updates. See separate notification chains per data source.
Design and implement a generic notification chain in C, a linked list of notification chain elements with keys and function pointers, plus a generic callback prototype.
Implement a publisher-subscriber model with a routing table data source, where one publisher thread serves four entries and three subscriber threads subscribe to specific entries via per-entry notification chains.
Model a routing table as a data source using a doubly linked list, defining keys (destination, mask) and entries with interface and gateway, and implement CRUD APIs.
Compile using below commands :
gcc -g -c rtm_publisher.c -o rtm_publisher.o
gcc -g -c rt.c -o rt.o ( assuming you have renamed rt_raw.c and rt_raw.h to rt.c and rt.h )
gcc -g rtm_publisher.o rt.o -o main.exe -lpthread
Run : ./main.exe
implement subscriber support in threaded_subscriber.c by creating a detached subscriber thread, subscribing to random routing table entries, and handling publisher notifications via a test callback, integrating with the notification chains.
Implement subscription and notification in a publisher-subscriber model using a routing table data source; let subscribers express interest and receive updates when the publisher modifies entries.
Implement the subscription API to register subscribers for routing table entries, create entries when needed, initialize and register notification chain elements, and immediately notify entries with the NFC add opcode.
Enhance the routing table with a notification chain that informs all subscribers on updates, additions, and deletions, distinguishing publisher updates from subscriber creates and ensuring proper memory cleanup.
Demonstrate inter-thread communication via a publisher-subscriber model, where the publisher updates a routing table and notifies subscriber threads with the new data.
Explore thread cancellation, stopping a running thread to cancel ongoing searches, periodic packets, or file downloads, with any thread in the same process able to cancel another and terminate it.
Learn how to implement asynchronous thread cancellation in POSIX threads by using pthread_cancel, pthread_setcancelstate, and pthread_setcanceltype, including making threads cancelable and the limits of canceling non-cancellable threads.
Illustrate how asynchronous thread cancellation can leave data structures in an invariant state, causing corruption, memory leaks, and wrong results, with examples from doubly linked lists and balanced trees.
Install and balance pthread cleanup handlers in the thread function to free heap memory and close a file upon cancellation, and then demonstrate with a compile-and-run script.
Understand listener threads and their slave design that monitor external events—packets arriving on UDP sockets, kernel events, and user input—and delegate processing to the main process without blocking.
Launch two UDP listener threads on 127.0.0.1 ports 3000 and 3001 to feed packets into the main application via a simple receive function, while a third thread handles user interaction.
Create two listener threads on ports 3000 and 3001 using server_create_and_start with ip 127.0.0.1, and implement a packet_receive function that prints received packet and its size, then exits via pthread_exit.
Implement a UDP packet listener thread in C using pthreads: create a detached thread, bind a UDP socket to IP address and port, and invoke a callback on packet arrival.
Identify critical sections that access shared data, such as global variables or file descriptors, and synchronize them so only one thread accesses them at a time to prevent data corruption.
Learn how mutexes enforce mutual exclusivity to protect a critical section in multithreading, using the locker-key analogy to illustrate access control and practice through problems.
Master mutex rules for thread synchronization: only the locking thread should unlock its mutex, and avoid unlocking an already unlocked mutex; blocking, scheduling, and the reverse-order unlock complete correct usage.
Explore mutex locking and differentiate code locking from object locking, using a global mutex in a file to protect critical sections with pthread mutex lock and unlock.
Data locking uses a mutex owned by each list object to guard its critical sections, enabling concurrency across different lists and avoiding unnecessary blocking from code locking.
Explore a mutexes in action demonstration where two threads read and write a shared array, producing undefined behavior, then learn to enforce mutual exclusion with mutexes.
Deploy mutexes to enforce mutual exclusion between two threads accessing a shared array, guarding read and write operations and ensuring the sum equals 15.
Welcome to the Course Series on Multi-Threading - The Master Class Course on Threads.
This course is for those who want to develop fundamental concepts on Multi-threading and related concepts. In this course, we shall be going to cover Multi-threading concepts based on Pthreads (POSIX threads) on the Linux platform.
Though We use the C language to demonstrate the concepts, concepts hold good for any programming language. This course is equally valuable for C++ programmers. Other language programmers may also find this course useful as we explain Multithreading concepts close to the ground zero levels No Abstraction.
We shall discuss several concepts involved in multithreading and demonstrate each concept through a sample program. Several Important Concepts include but are not limited to - Deadlocks, Mutual Exclusion, Atomicity, Thread Synchronization, Race Conditions, Thread forking, and many more.
In the Next Installment of this course, we shall extend our knowledge of Multi-threading to Advance Concepts, including mini-projects on Multithreading and Thread Synchronization.
At each stage of this Course series, you shall be writing a lot of multi-threaded Codes. So be ready to Master the Multi-threading. Along the journey, we shall cover several interview-favorite topics and Questions to prepare you alongside for interviews.
Best of luck!
Table Of Contents:
= = = ======= = = =
1. Understanding Threads
Thread Creation & Termination
Race condition on Thread Creation
Passing Argument to Thread Function
Stack Memory Mgmt for Multi-threaded Programs
Thread Scheduling
2. Understanding Concurrency and Parallelism
Singlularism Vs Concurrency Vs Parallelism
Concurrent Process Design - 2 Examples
Threads as Light Weighted Process
Overlapping and Non-Overlapping Work
3. Joinable and Detached Threads
Joinable Vs Detached Threads
How to Join a thread
Whom to Join?
Sample - Map-Reduce Program
4. Inter Thread Communication
Understanding Callbacks and Function Pointers
Best way to implement ITC
Implementing Notification Chains
A Publisher Subscriber Model
How to Subscribe/UnSubscribe
How to send Notification to Subscribers
5. Asynchronous Thread Cancellation
Thread Cancellation
Asynchronous and Deferred Thread Cancellation
Problem with Async Thread Cancellation
Resource Leaking
Invariants
Deadlocks
Concept of Thread Cleanup Handlers
Prevent Resource Leaking
Data Structure Corruption - Invariants
Cancellation causing Deadlocks
6. Deferred Cancellation
Understanding Deferred Cancellation
Implementation
7. Listener Threads - Responsibility Delegation
Why Listener threads?
Designing Listener threads
Code Changes and Demo
Cancellation of blocked Threads
8. Thread Synchronization
Critical Section
Mutex Rules
Mutex Locking
Mutex Locking - Code Locking
Mutex Locking - Data Locking
Mutex based APIs
Mutexes in Action
9. Deadlocks
What are deadlocks and why do they happen?
Necessary conditions for Deadlock to happen
Mutex lock Ordering Causing Deadlocks
10. Condition Variables
Understanding CV
CV Vs Mutex
Wait( ) & Signal( )
Producer-Consumer Thread Synchronization
Spurious Wake Ups
Thread Vs Resource Specific CV
Broadcasting a CV
Implement Producer-Consumer Problem
11. Dining Philosopher Problem
Problem Description
Data Structures Setup
Assignment Program Setup
Flowchart/Algorithm Discussion
Final Implementation (Step by Step )
12. Semaphores
Introduction
Semaphores Vs Mutexes
How Semaphore work
Strict Alternation Problem
Semaphore Implementation
Semaphore Types
Strong and Weak Semaphores
Listing Upcoming Advanced Multi-Threading Topics for Sequel Course ( Under Progress )
= = = = = = = = = = = = = = = = = = = = = =
1. Pausing and Resuming Threads
2. Thread Pools
3. Standard Problems - Reader/Writer Problem
4. Implementing Thread Barriers
5. Implementing Thread Monitors
6. Solving Sync Problems using Monitors
7. Deadlock Detection and Prevention
8. Wait Queues
9. Implement Timers using Threads
10. How to fork a multi-threaded process
11. Process Synchronization using Named Semaphores
Happy Learning.
Featured Review
This course is amazing. I'm so glad the instructor decided to offer courses on Udemy. First, it's very rare to find courses on more advanced subject matter. As a software developer, I love learning but am often disappointed that Udemy largely has beginner-oriented material (understandably so). Then there's the CSEPracticals courses. I learned a LOT here. This is some valuable, real world stuff. It's incredibly useful to learn how multi-threading in C is actually applied in real world use cases and to implement these use cases on your own. The instruction was clear, the information valuable. The code samples are plentiful. The instructor is clearly very knowledgeable about networking and so the course examples tend to lean in that direction. I'm very impressed and had a LOT of fun with this course. I can't wait to check out the other ones by CSEPracticals.
I have just finished this course, and I cannot recommend it more. Its an excellent course on multi-threading and achieves exactly what it intends to from the start. Some features of this course 1) You write a lot of code, and you become more confident in using the pthread library ( along with some other things, I learned how important proper use of assert function can be). 2) Abishekh goes in depth on different synchronization method and shows you have to build them using fundamental tools like mutex and condition variables. This gives you a lot of confidence, and you can build your own in future in case your chosen OS or library does not have those built-in. This in my opinion is the biggest strength of the course. 3) The team of CSE Practicals is very responsive and you can expect to get a response on your queries within a very reasonable time-frame. Ongoing to the course sequel now. Ovais