Multithreading and Parallelism
Contents
Multithreading, Concurrency, and Parallelism in Computing
1. What is Multithreading?
- Multithreading: The ability of a CPU (or a single process) to manage multiple threads of execution concurrently.
- Threads share process resources (memory, file descriptors), but each has its own execution context (registers, stack).
- Used for responsiveness, task separation, and efficient CPU use.
1.1 Example Usage:
- A GUI application runs its interface in one thread and background tasks (e.g., downloads) in another.
- Servers use worker threads to handle multiple client connections.
1.2 C Example: Simple Thread Creation (POSIX pthreads)
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void* worker(void* arg) {
int n = *(int*)arg;
printf("Worker thread running with n = %d\n", n);
sleep(1);
printf("Worker thread done\n");
return NULL;
}
int main() {
pthread_t tid;
int n = 42;
pthread_create(&tid, NULL, worker, &n);
printf("Main thread continues\n");
pthread_join(tid, NULL); // Wait for worker to finish
printf("Main thread exits\n");
return 0;
}
Main thread continues
Worker thread running with n = 42
Worker thread done
Main thread exits
2. What is Concurrency?
- Concurrency: Managing multiple tasks at once, but not necessarily simultaneously.
- Achieved via interleaved execution (context switching), often on a single-core CPU.
- Focuses on structure and coordination of tasks, not their simultaneous execution.
2.1 Example Usage:
- Handling multiple client requests in a web server by switching between them rapidly.
- Producer-consumer problems, where producer and consumer share a buffer.
2.2 C Example: Producer-Consumer with Mutex and Condition Variable
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#define BUF_SIZE 5
int buffer[BUF_SIZE], count = 0;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t not_full = PTHREAD_COND_INITIALIZER, not_empty = PTHREAD_COND_INITIALIZER;
void* producer(void* _) {
for (int i = 0; i < 10; ++i) {
pthread_mutex_lock(&mtx);
while (count == BUF_SIZE) pthread_cond_wait(¬_full, &mtx);
buffer[count++] = i;
printf("Produced %d\n", i);
pthread_cond_signal(¬_empty);
pthread_mutex_unlock(&mtx);
usleep(100000);
}
return NULL;
}
void* consumer(void* _) {
for (int i = 0; i < 10; ++i) {
pthread_mutex_lock(&mtx);
while (count == 0) pthread_cond_wait(¬_empty, &mtx);
int val = buffer[--count];
printf("Consumed %d\n", val);
pthread_cond_signal(¬_full);
pthread_mutex_unlock(&mtx);
usleep(150000);
}
return NULL;
}
int main() {
pthread_t prod, cons;
pthread_create(&prod, NULL, producer, NULL);
pthread_create(&cons, NULL, consumer, NULL);
pthread_join(prod, NULL);
pthread_join(cons, NULL);
return 0;
}
Produced 0
Consumed 0
Produced 1
Consumed 1
Produced 2
Consumed 2
Produced 3
Produced 4
Consumed 4
Produced 5
Consumed 5
Produced 6
Produced 7
Consumed 7
Produced 8
Consumed 8
Produced 9
Consumed 9
Consumed 6
Consumed 3
3. What is Parallelism?
- Parallelism: Performing multiple computations simultaneously on different processors or cores.
- Requires multi-core CPUs, multiple processors, or hardware acceleration.
- Focuses on actual simultaneous execution for faster completion.
3.1 Example Usage:
- Scientific simulations dividing work among CPU cores.
- Multimedia processing: one core decodes video, another processes audio.
3.2 C Example: Parallel Array Sum Using Threads
#include <pthread.h>
#include <stdio.h>
#define N 1000000
#define THREADS 4
int array[N];
long long partial_sum[THREADS];
void* sum_array(void* arg) {
int idx = *(int*)arg;
int chunk = N / THREADS;
int start = idx * chunk;
int end = (idx == THREADS-1) ? N : start + chunk;
long long sum = 0;
for (int i = start; i < end; ++i) sum += array[i];
partial_sum[idx] = sum;
return NULL;
}
int main() {
for (int i = 0; i < N; ++i) array[i] = 1; // Fill with 1s
pthread_t tids[THREADS];
int ids[THREADS];
for (int i = 0; i < THREADS; ++i) {
ids[i] = i;
pthread_create(&tids[i], NULL, sum_array, &ids[i]);
}
long long total = 0;
for (int i = 0; i < THREADS; ++i) {
pthread_join(tids[i], NULL);
total += partial_sum[i];
}
printf("Total sum: %lld\n", total);
return 0;
}
Total sum: 1000000
4. Concurrency vs Parallelism vs Multithreading
Aspect | Concurrency | Parallelism | Multithreading |
---|---|---|---|
Key Focus | Task structure/coordination | Simultaneous execution | Multiple threads per process |
Hardware | Not required (can be 1 CPU) | Requires >1 CPU/core | Supported by most OS/CPUs |
Example | Producer-consumer, async IO | Matrix multiply on 8 cores | GUI thread + worker threads |
Code Example | Mutexes, semaphores | Thread pools, OpenMP | pthreads, Java threads |
5. Practical Uses and Issues
- Responsiveness (GUIs, games): main thread for UI, workers for background.
- Servers: Handle many clients using thread pools.
- Scientific/financial: Distribute heavy computation across cores (parallelism).
- Challenges: race conditions, deadlocks, false sharing, thread contention, debugging complexity.
6. Tools, Libraries, and Extensions
- POSIX threads (pthreads): Standard in C for Linux/Unix.
- OpenMP: High-level API for parallel loops.
- std::thread (C++11+), Java threads.
- Thread sanitizer, Helgrind, Valgrind for debugging.