Simple Tutorial: Understanding Threads in C
Programming
What are Threads? (Simple Explanation)
Think of a thread like having multiple people working on different tasks at the same time in the same
office. Each person (thread) can work independently, but they all share the same office space
(memory).[1][2]
Real-world example:
• Like listening to music while typing a document
• Your computer does both tasks at the same time
• Each task runs in its own "thread"
Why Use Threads?
1. Speed: Multiple things happen at once instead of waiting for each task to finish[3][1]
2. Efficiency: Better use of computer resources
3. Responsiveness: Program doesn't freeze while doing heavy work
Basic Setup
Step 1: Include the Thread Library
#include <pthread.h> // This gives us thread functions
#include <stdio.h> // This gives us printf function
#include <unistd.h> // This gives us sleep function
Step 2: Compile Command
gcc filename.c -o filename -lpthread
Note: The -lpthread part is very important - it links the thread library
Core Thread Functions (Simplified)
1. Creating a Thread: pthread_create()
What it does: Creates a new thread (like hiring a new worker)[1][3]
Simple Syntax:
pthread_create(&thread_id, NULL, function_name, &argument);
Parameters Explained:
• &thread_id → Where to store the new thread's ID number
• NULL → Use default settings (don't worry about this for now)
• function_name → What job should the thread do (function name)
• &argument → Information to give to the thread (use NULL if none)
2. Waiting for a Thread: pthread_join()
What it does: Makes main program wait until thread finishes (like waiting for a worker to complete their
task)[4][3]
Simple Syntax:
pthread_join(thread_id, NULL);
Parameters Explained:
• thread_id → Which thread to wait for
• NULL → Don't store return value (keep it simple)
3. Ending a Thread: pthread_exit()
What it does: Thread says "I'm done with my work" and exits[5][3]
Simple Syntax:
pthread_exit(NULL);
Program 1: Your First Thread Program
This program creates one thread that prints messages while the main program also prints messages.[6][7]
#include <stdio.h> // For printf function
#include <pthread.h> // For thread functions
#include <unistd.h> // For sleep function
// This is the function that our thread will run
// Every thread function must look like this: void* name(void* arg)
void* my_thread_function(void* arg) {
// Print a message from the thread
printf("Hello! I am a thread!\n");
// Make the thread sleep for 2 seconds to show it's working
sleep(2);
// Print another message
printf("Thread: I finished my work!\n");
// End the thread properly
pthread_exit(NULL);
}
int main() {
// Step 1: Create a variable to store thread information
pthread_t my_thread;
printf("Main program: Starting...\n");
// Step 2: Create the thread
// This tells the thread to run "my_thread_function"
if (pthread_create(&my_thread, NULL, my_thread_function, NULL) != 0) {
printf("Error: Could not create thread!\n");
return 1; // Exit program if thread creation failed
}
printf("Main program: Thread created successfully!\n");
// Step 3: Do some work in main program while thread is running
printf("Main program: I'm doing my own work...\n");
sleep(1); // Simulate some work
printf("Main program: Still working...\n");
// Step 4: Wait for the thread to finish
printf("Main program: Waiting for thread to finish...\n");
pthread_join(my_thread, NULL);
// Step 5: Thread is done, main program continues
printf("Main program: Thread finished! Program ending.\n");
return 0; // Program ends successfully
}
How to run this:
1. Save as first_thread.c
2. Compile: gcc first_thread.c -o first_thread -lpthread
3. Run: ./first_thread
Expected Output:
Main program: Starting...
Main program: Thread created successfully!
Hello! I am a thread!
Main program: I'm doing my own work...
Main program: Still working...
Main program: Waiting for thread to finish...
Thread: I finished my work!
Main program: Thread finished! Program ending.
Program 2: Thread with Data
This shows how to send information to a thread (like giving instructions to a worker).[8][6]
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
// Function that thread will run
// The "arg" parameter contains data we send to the thread
void* worker_thread(void* arg) {
// Convert the argument back to an integer
// (This is like opening an envelope to read the message inside)
int worker_number = *(int*)arg;
printf("Worker %d: I'm starting my work!\n", worker_number);
// Simulate different amounts of work for each worker
sleep(worker_number);
printf("Worker %d: I finished my work! It took %d seconds.\n",
worker_number, worker_number);
// Thread finishes
pthread_exit(NULL);
}
int main() {
// Variables to store thread information
pthread_t worker1, worker2, worker3;
// Data to send to each thread (like giving each worker different instructions)
int task1 = 1; // Worker 1 gets task "1"
int task2 = 2; // Worker 2 gets task "2"
int task3 = 3; // Worker 3 gets task "3"
printf("Boss: I'm hiring 3 workers...\n");
// Create first worker thread and give it task1
pthread_create(&worker1, NULL, worker_thread, &task1);
printf("Boss: Worker 1 hired!\n");
// Create second worker thread and give it task2
pthread_create(&worker2, NULL, worker_thread, &task2);
printf("Boss: Worker 2 hired!\n");
// Create third worker thread and give it task3
pthread_create(&worker3, NULL, worker_thread, &task3);
printf("Boss: Worker 3 hired!\n");
printf("Boss: All workers are working. I'll wait for them...\n");
// Wait for all workers to finish (in order)
pthread_join(worker1, NULL);
printf("Boss: Worker 1 is done!\n");
pthread_join(worker2, NULL);
printf("Boss: Worker 2 is done!\n");
pthread_join(worker3, NULL);
printf("Boss: Worker 3 is done!\n");
printf("Boss: All work completed! Closing office.\n");
return 0;
}
How to run:
1. Save as worker_threads.c
2. Compile: gcc worker_threads.c -o worker_threads -lpthread
3. Run: ./worker_threads
Program 3: Simple Counter Example
This shows threads working with shared data (like multiple people adding numbers to the same
calculator).[9][6]
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
// Shared variable - both threads can access this
int shared_counter = 0;
// Thread function that adds numbers to the counter
void* counting_thread(void* arg) {
int thread_id = *(int*)arg;
printf("Counter Thread %d: I will add 5 to the counter\n", thread_id);
// Add 5 to the shared counter, one at a time
for (int i = 1; i <= 5; i++) {
shared_counter = shared_counter + 1; // Add 1 to counter
printf("Thread %d: Added 1, counter is now: %d\n", thread_id, shared_counter);
sleep(1); // Wait 1 second between additions
}
printf("Counter Thread %d: I'm done adding!\n", thread_id);
pthread_exit(NULL);
}
int main() {
pthread_t counter1, counter2;
int id1 = 1, id2 = 2;
printf("Main: Starting with counter = %d\n", shared_counter);
// Create two threads that will both add to the same counter
printf("Main: Creating two counter threads...\n");
pthread_create(&counter1, NULL, counting_thread, &id1);
pthread_create(&counter2, NULL, counting_thread, &id2);
printf("Main: Both threads are running and adding to the counter!\n");
// Wait for both threads to finish
pthread_join(counter1, NULL);
pthread_join(counter2, NULL);
printf("Main: Final counter value is: %d\n", shared_counter);
printf("Main: Program finished!\n");
return 0;
}
Key Points to Remember
1. Always include #include <pthread.h>[10][1]
2. Always compile with -lpthread flag
3. Thread functions must have this format: void* function_name(void* arg)[7][3]
4. Always use pthread_join() to wait for threads to finish[3][4]
5. Use pthread_exit(NULL) to end threads properly[5][3]
Common Beginner Mistakes
1. Forgetting -lpthread when compiling → Program won't compile
2. Not using pthread_join() → Main program might end before threads finish
3. Wrong thread function format → Compiler errors
4. Not checking if thread creation succeeded → Program might crash
What You Learned
• Threads let multiple tasks run at the same time[2][1]
• pthread_create() starts a new thread[1][3]
• pthread_join() waits for a thread to finish[4][3]
• Threads can share data but need to be careful[6][9]
• Always compile with -lpthread flag