UNIX threads:
1. Introduction to threads (pthreads)
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* routine() {
printf("Hello from threads\n");
sleep(3);
printf("Ending thread\n");
}
int main(int argc, char* argv[]) {
pthread_t p1, p2;
if (pthread_create(&p1, NULL, &routine, NULL) != 0) {
return 1;
}
if (pthread_create(&p2, NULL, &routine, NULL) != 0) {
return 2;
}
if (pthread_join(p1, NULL) != 0) {
return 3;
}
if (pthread_join(p2, NULL) != 0) {
return 4;
}
return 0;
}
2. Difference between processes and threads
main-processes.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
int main(int argc, char* argv[]) {
int x = 2;
int pid = fork();
if (pid == -1) {
return 1;
}
if (pid == 0) {
x++;
}
sleep(2);
printf("Value of x: %d\n", x);
if (pid != 0) {
wait(NULL);
}
return 0;
}
main-threads.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int x = 2;
void* routine() {
x += 5;
sleep(2);
printf("Value of x: %d\n", x);
}
void* routine2() {
sleep(2);
printf("Value of x: %d\n", x);
}
int main(int argc, char* argv[]) {
pthread_t t1, t2;
if (pthread_create(&t1, NULL, &routine, NULL)) {
return 1;
}
if (pthread_create(&t2, NULL, &routine2, NULL)) {
return 2;
}
if (pthread_join(t1, NULL)) {
return 3;
}
if (pthread_join(t2, NULL)) {
return 3;
}
return 0;
}
3. What are Race Conditions?
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
int mails = 0;
void* routine() {
for (int i = 0; i < 1000000; i++) {
mails++;
// read mails
// increment
// write mails
}
}
int main(int argc, char* argv[]) {
pthread_t p1, p2, p3, p4;
if (pthread_create(&p1, NULL, &routine, NULL) != 0) {
return 1;
}
if (pthread_create(&p2, NULL, &routine, NULL) != 0) {
return 2;
}
if (pthread_join(p1, NULL) != 0) {
return 3;
}
if (pthread_join(p2, NULL) != 0) {
return 4;
}
printf("Number of mails: %d\n", mails);
return 0;
}
4. What is a mutex in C? (pthread_mutex)
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
int mails = 0;
pthread_mutex_t mutex;
void* routine() {
for (int i = 0; i < 10000000; i++) {
pthread_mutex_lock(&mutex);
mails++;
pthread_mutex_unlock(&mutex);
// read mails
// increment
// write mails
}
}
int main(int argc, char* argv[]) {
pthread_t p1, p2, p3, p4;
pthread_mutex_init(&mutex, NULL);
if (pthread_create(&p1, NULL, &routine, NULL) != 0) {
return 1;
}
if (pthread_create(&p2, NULL, &routine, NULL) != 0) {
return 2;
}
if (pthread_create(&p3, NULL, &routine, NULL) != 0) {
return 3;
}
if (pthread_create(&p4, NULL, &routine, NULL) != 0) {
return 4;
}
if (pthread_join(p1, NULL) != 0) {
return 5;
}
if (pthread_join(p2, NULL) != 0) {
return 6;
}
if (pthread_join(p3, NULL) != 0) {
return 7;
}
if (pthread_join(p4, NULL) != 0) {
return 8;
}
pthread_mutex_destroy(&mutex);
printf("Number of mails: %d\n", mails);
return 0;
}
5. How to create threads in a loop (pthread_create)
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
int mails = 0;
pthread_mutex_t mutex;
void* routine() {
for (int i = 0; i < 10000000; i++) {
pthread_mutex_lock(&mutex);
mails++;
pthread_mutex_unlock(&mutex);
}
}
int main(int argc, char* argv[]) {
pthread_t th[8];
int i;
pthread_mutex_init(&mutex, NULL);
for (i = 0; i < 8; i++) {
if (pthread_create(th + i, NULL, &routine, NULL) != 0) {
perror("Failed to create thread");
return 1;
}
printf("Thread %d has started\n", i);
}
for (i = 0; i < 8; i++) {
if (pthread_join(th[i], NULL) != 0) {
return 2;
}
printf("Thread %d has finished execution\n", i);
}
pthread_mutex_destroy(&mutex);
printf("Number of mails: %d\n", mails);
return 0;
}
6. Get return value from a thread (pthread_join)
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
void* roll_dice() {
int value = (rand() % 6) + 1;
int* result = malloc(sizeof(int));
*result = value;
// printf("%d\n", value);
printf("Thread result: %p\n", result);
return (void*) result;
}
int main(int argc, char* argv[]) {
int* res;
srand(time(NULL));
pthread_t th;
if (pthread_create(&th, NULL, &roll_dice, NULL) != 0) {
return 1;
}
if (pthread_join(th, (void**) &res) != 0) {
return 2;
}
printf("Main res: %p\n", res);
printf("Result: %d\n", *res);
free(res);
return 0;
}
7. How to pass arguments to threads in C
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int primes[10] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
void* routine(void* arg) {
sleep(1);
int index = *(int*)arg;
printf("%d ", primes[index]);
free(arg);
}
int main(int argc, char* argv[]) {
pthread_t th[10];
int i;
for (i = 0; i < 10; i++) {
int* a = malloc(sizeof(int));
*a = i;
if (pthread_create(&th[i], NULL, &routine, a) != 0) {
perror("Failed to created thread");
}
}
for (i = 0; i < 10; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
return 0;
}
8. Example: Summing numbers from an array
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int primes[10] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
void* routine(void* arg) {
int index = *(int*)arg;
int sum = 0;
for (int j = 0; j < 5; j++) {
sum += primes[index + j];
}
printf("Local sum: %d\n", sum);
*(int*)arg = sum;
return arg;
}
int main(int argc, char* argv[]) {
pthread_t th[2];
int i;
for (i = 0; i < 2; i++) {
int* a = malloc(sizeof(int));
*a = i * 5;
if (pthread_create(&th[i], NULL, &routine, a) != 0) {
perror("Failed to create thread");
}
}
int globalSum = 0;
for (i = 0; i < 2; i++) {
int* r;
if (pthread_join(th[i], (void**) &r) != 0) {
perror("Failed to join thread");
}
globalSum += *r;
free(r);
}
printf("Global sum: %d\n", globalSum);
return 0;
}
9. Difference between trylock and lock in C
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
pthread_mutex_t mutex;
void* routine_lock(void* arg) {
pthread_mutex_lock(&mutex);
printf("Got lock\n");
sleep(1);
pthread_mutex_unlock(&mutex);
}
void* routine_trylock(void* arg) {
if (pthread_mutex_trylock(&mutex) == 0) {
printf("Got lock\n");
sleep(1);
pthread_mutex_unlock(&mutex);
} else {
printf("Didn't get lock\n");
}
}
int main(int argc, char* argv[]) {
pthread_t th[4];
pthread_mutex_init(&mutex, NULL);
for (int i = 0; i < 4; i++) {
if (pthread_create(&th[i], NULL, &routine, NULL) != 0) {
perror("Error at creating thread");
}
}
for (int i = 0; i < 4; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Error at joining thread");
}
}
pthread_mutex_destroy(&mutex);
return 0;
}
10. Condition variables in C
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
pthread_mutex_t mutexFuel;
pthread_cond_t condFuel;
int fuel = 0;
void* fuel_filling(void* arg) {
for (int i = 0; i < 5; i++) {
pthread_mutex_lock(&mutexFuel);
fuel += 15;
printf("Filled fuel... %d\n", fuel);
pthread_mutex_unlock(&mutexFuel);
pthread_cond_signal(&condFuel);
sleep(1);
}
}
void* car(void* arg) {
pthread_mutex_lock(&mutexFuel);
while (fuel < 40) {
printf("No fuel. Waiting...\n");
pthread_cond_wait(&condFuel, &mutexFuel);
// Equivalent to:
// pthread_mutex_unlock(&mutexFuel);
// wait for signal on condFuel
// pthread_mutex_lock(&mutexFuel);
}
fuel -= 40;
printf("Got fuel. Now left: %d\n", fuel);
pthread_mutex_unlock(&mutexFuel);
}
int main(int argc, char* argv[]) {
pthread_t th[2];
pthread_mutex_init(&mutexFuel, NULL);
pthread_cond_init(&condFuel, NULL);
for (int i = 0; i < 2; i++) {
if (i == 1) {
if (pthread_create(&th[i], NULL, &fuel_filling, NULL) != 0) {
perror("Failed to create thread");
}
} else {
if (pthread_create(&th[i], NULL, &car, NULL) != 0) {
perror("Failed to create thread");
}
}
}
for (int i = 0; i < 2; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
pthread_mutex_destroy(&mutexFuel);
pthread_cond_destroy(&condFuel);
return 0;
}
11. Signaling for condition variables (pthread_cond_signal vs pthread_cond_broadcast)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
pthread_mutex_t mutexFuel;
pthread_cond_t condFuel;
int fuel = 0;
void* fuel_filling(void* arg) {
for (int i = 0; i < 5; i++) {
pthread_mutex_lock(&mutexFuel);
fuel += 30;
printf("Filled fuel... %d\n", fuel);
pthread_mutex_unlock(&mutexFuel);
pthread_cond_broadcast(&condFuel);
sleep(1);
}
}
void* car(void* arg) {
pthread_mutex_lock(&mutexFuel);
while (fuel < 40) {
printf("No fuel. Waiting...\n");
pthread_cond_wait(&condFuel, &mutexFuel);
// Equivalent to:
// pthread_mutex_unlock(&mutexFuel);
// wait for signal on condFuel
// pthread_mutex_lock(&mutexFuel);
}
fuel -= 40;
printf("Got fuel. Now left: %d\n", fuel);
pthread_mutex_unlock(&mutexFuel);
}
int main(int argc, char* argv[]) {
pthread_t th[6];
pthread_mutex_init(&mutexFuel, NULL);
pthread_cond_init(&condFuel, NULL);
for (int i = 0; i < 6; i++) {
if (i == 4 || i == 5) {
if (pthread_create(&th[i], NULL, &fuel_filling, NULL) != 0) {
perror("Failed to create thread");
}
} else {
if (pthread_create(&th[i], NULL, &car, NULL) != 0) {
perror("Failed to create thread");
}
}
}
for (int i = 0; i < 6; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
pthread_mutex_destroy(&mutexFuel);
pthread_cond_destroy(&condFuel);
return 0;
}
12. Example: pthread_mutex_trylock
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
// chefs = threads
// stove = shared data (+mutex)
pthread_mutex_t stoveMutex[4];
int stoveFuel[4] = { 100, 100, 100, 100 };
void* routine(void* args) {
for (int i = 0; i < 4; i++) {
if (pthread_mutex_trylock(&stoveMutex[i]) == 0) {
int fuelNeeded = (rand() % 30);
if (stoveFuel[i] - fuelNeeded < 0) {
printf("No more fuel... going home\n");
} else {
stoveFuel[i] -= fuelNeeded;
usleep(500000);
printf("Fuel left %d\n", stoveFuel[i]);
}
pthread_mutex_unlock(&stoveMutex[i]);
break;
} else {
if (i == 3) {
printf("No stove available yet, waiting...\n");
usleep(300000);
i = 0;
}
}
}
}
int main(int argc, char* argv[]) {
srand(time(NULL));
pthread_t th[10];
for (int i = 0; i < 4; i++) {
pthread_mutex_init(&stoveMutex[i], NULL);
}
for (int i = 0; i < 10; i++) {
if (pthread_create(&th[i], NULL, &routine, NULL) != 0) {
perror("Failed to create thread");
}
}
for (int i = 0; i < 10; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
for (int i = 0; i < 4; i++) {
pthread_mutex_destroy(&stoveMutex[i]);
}
return 0;
}
13. What is pthread_exit?
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
void* roll_dice() {
int value = (rand() % 6) + 1;
int* result = malloc(sizeof(int));
*result = value;
sleep(2);
printf("Thread result: %d\n", value);
pthread_exit((void*) result);
}
int main(int argc, char* argv[]) {
int* res;
srand(time(NULL));
pthread_t th;
if (pthread_create(&th, NULL, &roll_dice, NULL) != 0) {
return 1;
}
// pthread_exit(0);
if (pthread_join(th, (void**) &res) != 0) {
return 2;
}
printf("Result: %d\n", *res);
free(res);
return 0;
}
14. Introduction to barriers (pthread_barrier)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
pthread_barrier_t barrier;
void* routine(void* args) {
while (1) {
printf("Waiting at the barrier...\n");
sleep(1);
pthread_barrier_wait(&barrier);
printf("We passed the barrier\n");
sleep(1);
}
}
int main(int argc, char *argv[]) {
pthread_t th[10];
int i;
pthread_barrier_init(&barrier, NULL, 10);
for (i = 0; i < 10; i++) {
if (pthread_create(&th[i], NULL, &routine, NULL) != 0) {
perror("Failed to create thread");
}
}
for (i = 0; i < 10; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
pthread_barrier_destroy(&barrier);
return 0;
}
15. Example: barriers (pthread_barrier)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#define THREAD_NUM 8
int dice_values[THREAD_NUM];
int status[THREAD_NUM] = { 0 };
pthread_barrier_t barrierRolledDice;
pthread_barrier_t barrierCalculated;
void* roll(void* args) {
int index = *(int*)args;
while (1) {
dice_values[index] = rand() % 32 + 1;
pthread_barrier_wait(&barrierRolledDice);
pthread_barrier_wait(&barrierCalculated);
if (status[index] == 1) {
printf("(%d rolled %d) I won\n", index, dice_values[index]);
} else {
printf("(%d rolled %d) I lost\n", index, dice_values[index]);
}
}
free(args);
}
int main(int argc, char *argv[]) {
srand(time(NULL));
pthread_t th[THREAD_NUM];
int i;
pthread_barrier_init(&barrierRolledDice, NULL, THREAD_NUM + 1);
pthread_barrier_init(&barrierCalculated, NULL, THREAD_NUM + 1);
for (i = 0; i < THREAD_NUM; i++) {
int* a = malloc(sizeof(int));
*a = i;
if (pthread_create(&th[i], NULL, &roll, (void*) a) != 0) {
perror("Failed to create thread");
}
}
while (1) {
pthread_barrier_wait(&barrierRolledDice);
// Calculate winner
int max = 0;
for (i = 0; i < THREAD_NUM; i++) {
if (dice_values[i] > max) {
max = dice_values[i];
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (dice_values[i] == max) {
status[i] = 1;
} else {
status[i] = 0;
}
}
sleep(1);
printf("==== New round starting ====\n");
pthread_barrier_wait(&barrierCalculated);
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
pthread_barrier_destroy(&barrierRolledDice);
pthread_barrier_destroy(&barrierCalculated);
return 0;
}
16. What is pthread_t?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/syscall.h>
#define THREAD_NUM 2
void* routine(void* args) {
pthread_t th = pthread_self();
printf("%ul\n", th);
printf("%d\n", (pid_t) syscall(SYS_gettid));
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_create(&th[i], NULL, &routine, NULL) != 0) {
perror("Failed to create thread");
}
// printf("%ul\n", th[i]);
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
return 0;
}
17. What are detached threads?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#define THREAD_NUM 2
void* routine(void* args) {
sleep(1);
printf("Finished execution\n");
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
pthread_attr_t detachedThread;
pthread_attr_init(&detachedThread);
pthread_attr_setdetachstate(&detachedThread, PTHREAD_CREATE_DETACHED);
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_create(&th[i], &detachedThread, &routine, NULL) != 0) {
perror("Failed to create thread");
}
// pthread_detach(th[i]);
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
pthread_attr_destroy(&detachedThread);
pthread_exit(0);
}
18. Static initializers in the PTHREAD API
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#define THREAD_NUM 2
pthread_mutex_t mutexFuel = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condFuel = PTHREAD_COND_INITIALIZER;
void* routine(void* args) {
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_create(&th[i], NULL, &routine, NULL) != 0) {
perror("Failed to create thread");
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
return 0;
}
19. Deadlocks in C
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#define THREAD_NUM 8
pthread_mutex_t mutexFuel;
int fuel = 50;
pthread_mutex_t mutexWater;
int water = 10;
void* routine(void* args) {
if (rand() % 2 == 0) {
pthread_mutex_lock(&mutexFuel);
sleep(1);
pthread_mutex_lock(&mutexWater);
} else {
pthread_mutex_lock(&mutexWater);
sleep(1);
pthread_mutex_lock(&mutexFuel);
}
fuel += 50;
water = fuel;
printf("Incremented fuel to: %d set water to %d\n", fuel, water);
pthread_mutex_unlock(&mutexFuel);
pthread_mutex_unlock(&mutexWater);
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
pthread_mutex_init(&mutexFuel, NULL);
pthread_mutex_init(&mutexWater, NULL);
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_create(&th[i], NULL, &routine, NULL) != 0) {
perror("Failed to create thread");
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
printf("Fuel: %d\n", fuel);
printf("Water: %d\n", water);
pthread_mutex_destroy(&mutexFuel);
pthread_mutex_destroy(&mutexWater);
return 0;
}
20. Recursive mutexes
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define THREAD_NUM 8
pthread_mutex_t mutexFuel;
int fuel = 50;
void* routine(void* args) {
pthread_mutex_lock(&mutexFuel);
pthread_mutex_lock(&mutexFuel);
pthread_mutex_lock(&mutexFuel);
pthread_mutex_lock(&mutexFuel);
pthread_mutex_lock(&mutexFuel);
fuel += 50;
printf("Incremented fuel to %d\n", fuel);
pthread_mutex_unlock(&mutexFuel);
pthread_mutex_unlock(&mutexFuel);
pthread_mutex_unlock(&mutexFuel);
pthread_mutex_unlock(&mutexFuel);
pthread_mutex_unlock(&mutexFuel);
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
pthread_mutexattr_t recursiveMutexAttributes;
pthread_mutexattr_init(&recursiveMutexAttributes);
pthread_mutexattr_settype(&recursiveMutexAttributes, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutexFuel, &recursiveMutexAttributes);
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_create(&th[i], NULL, &routine, NULL) != 0) {
perror("Failed to create thread");
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
printf("Fuel: %d\n", fuel);
pthread_mutexattr_destroy(&recursiveMutexAttributes);
pthread_mutex_destroy(&mutexFuel);
return 0;
}
21. Introduction to semaphores in C
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#define THREAD_NUM 4
sem_t semaphore;
void* routine(void* args) {
sem_wait(&semaphore);
sleep(1);
printf("Hello from thread %d\n", *(int*)args);
sem_post(&semaphore);
free(args);
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
sem_init(&semaphore, 0, 4);
int i;
for (i = 0; i < THREAD_NUM; i++) {
int* a = malloc(sizeof(int));
*a = i;
if (pthread_create(&th[i], NULL, &routine, a) != 0) {
perror("Failed to create thread");
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
sem_destroy(&semaphore);
return 0;
}
22. Example: semaphores (Login Queue)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#define THREAD_NUM 16
sem_t semaphore;
void* routine(void* args) {
printf("(%d) Waiting in the login queue\n", *(int*)args);
sem_wait(&semaphore);
printf("(%d) Logged in\n", *(int*)args);
sleep(rand() % 5 + 1);
printf("(%d) Logged out\n", *(int*)args);
sem_post(&semaphore);
free(args);
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
sem_init(&semaphore, 0, 32);
int i;
for (i = 0; i < THREAD_NUM; i++) {
int* a = malloc(sizeof(int));
*a = i;
if (pthread_create(&th[i], NULL, &routine, a) != 0) {
perror("Failed to create thread");
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
sem_destroy(&semaphore);
return 0;
}
23. Producer - Consumer Problem in Multi-Threading
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <semaphore.h>
#define THREAD_NUM 8
sem_t semEmpty;
sem_t semFull;
pthread_mutex_t mutexBuffer;
int buffer[10];
int count = 0;
void* producer(void* args) {
while (1) {
// Produce
int x = rand() % 100;
sleep(1);
// Add to the buffer
sem_wait(&semEmpty);
pthread_mutex_lock(&mutexBuffer);
buffer[count] = x;
count++;
pthread_mutex_unlock(&mutexBuffer);
sem_post(&semFull);
}
}
void* consumer(void* args) {
while (1) {
int y;
// Remove from the buffer
sem_wait(&semFull);
pthread_mutex_lock(&mutexBuffer);
y = buffer[count - 1];
count--;
pthread_mutex_unlock(&mutexBuffer);
sem_post(&semEmpty);
// Consume
printf("Got %d\n", y);
sleep(1);
}
}
int main(int argc, char* argv[]) {
srand(time(NULL));
pthread_t th[THREAD_NUM];
pthread_mutex_init(&mutexBuffer, NULL);
sem_init(&semEmpty, 0, 10);
sem_init(&semFull, 0, 0);
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (i > 0) {
if (pthread_create(&th[i], NULL, &producer, NULL) != 0) {
perror("Failed to create thread");
}
} else {
if (pthread_create(&th[i], NULL, &consumer, NULL) != 0) {
perror("Failed to create thread");
}
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
sem_destroy(&semEmpty);
sem_destroy(&semFull);
pthread_mutex_destroy(&mutexBuffer);
return 0;
}
24. What are binary semaphores?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#define THREAD_NUM 1
sem_t semFuel;
pthread_mutex_t mutexFuel;
int *fuel;
void* routine(void* args) {
*fuel += 50;
printf("Current value is %d\n", *fuel);
sem_post(&semFuel);
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
fuel = malloc(sizeof(int));
*fuel = 50;
pthread_mutex_init(&mutexFuel, NULL);
sem_init(&semFuel, 0, 0);
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_create(&th[i], NULL, &routine, NULL) != 0) {
perror("Failed to create thread");
}
}
sem_wait(&semFuel);
printf("Deallocating fuel\n");
free(fuel);
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
pthread_mutex_destroy(&mutexFuel);
sem_destroy(&semFuel);
return 0;
}
25. Difference between Binary Semaphores and Mutexes
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#define THREAD_NUM 4
pthread_mutex_t mutexFuel;
sem_t semFuel;
int fuel = 50;
void* routine1(void* args) {
while (1) {
pthread_mutex_lock(&mutexFuel);
fuel += 50;
printf("Current value is %d\n", fuel);
}
}
void* routine2(void* args) {
while (1) {
pthread_mutex_unlock(&mutexFuel);
usleep(5000);
}
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
sem_init(&semFuel, 0, 1);
pthread_mutex_init(&mutexFuel, NULL);
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (i % 2 == 0) {
if (pthread_create(&th[i], NULL, &routine1, NULL) != 0) {
perror("Failed to create thread");
}
} else {
if (pthread_create(&th[i], NULL, &routine2, NULL) != 0) {
perror("Failed to create thread");
}
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
pthread_mutex_destroy(&mutexFuel);
sem_destroy(&semFuel);
return 0;
}
26. Getting the value of a semaphore
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#define THREAD_NUM 4
sem_t sem;
void* routine(void* args) {
int index = *(int*)args;
int semVal;
sem_wait(&sem);
sleep(index + 1);
sem_getvalue(&sem, &semVal);
printf("(%d) Current semaphore value after wait is %d\n", index, semVal);
sem_post(&sem);
sem_getvalue(&sem, &semVal);
printf("(%d) Current semaphore value after post is %d\n", index, semVal);
free(args);
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
sem_init(&sem, 0, 4);
int i;
for (i = 0; i < THREAD_NUM; i++) {
int* a = malloc(sizeof(int));
*a = i;
if (pthread_create(&th[i], NULL, &routine, a) != 0) {
perror("Failed to create thread");
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
sem_destroy(&sem);
return 0;
}
27. Parallelism vs Concurrency
main-parallelism.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define THREAD_NUM 2
int primes[10] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
void* routine(void* arg) {
int index = *(int*)arg;
int sum = 0;
sleep(1);
for (int j = 0; j < 5; j++) {
sum += primes[index + j];
}
printf("Local sum: %d\n", sum);
*(int*)arg = sum;
return arg;
}
int main(int argc, char* argv[]) {
pthread_t th[THREAD_NUM];
int i;
for (i = 0; i < THREAD_NUM; i++) {
int* a = malloc(sizeof(int));
*a = i * 5;
if (pthread_create(&th[i], NULL, &routine, a) != 0) {
perror("Failed to create thread");
}
}
int globalSum = 0;
for (i = 0; i < THREAD_NUM; i++) {
int* r;
if (pthread_join(th[i], (void**) &r) != 0) {
perror("Failed to join thread");
}
globalSum += *r;
free(r);
}
printf("Global sum: %d\n", globalSum);
return 0;
}
main-concurrency.c
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#define THREAD_NUM 16
int mails = 0;
pthread_mutex_t mutex;
void* routine() {
for (int i = 0; i < 10; i++) {
pthread_mutex_lock(&mutex);
mails++;
printf("Processing mail #%d\n", mails);
sleep(1);
pthread_mutex_unlock(&mutex);
}
}
int main(int argc, char* argv[]) {
pthread_t th[THREAD_NUM];
pthread_mutex_init(&mutex, NULL);
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_create(&th[i], NULL, &routine, NULL) != 0) {
perror("Failed to create thread");
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
pthread_mutex_destroy(&mutex);
printf("Number of mails: %d\n", mails);
return 0;
}
28. Thread Pools in C (using the PTHREAD API)
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define THREAD_NUM 4
typedef struct Task {
int a, b;
} Task;
Task taskQueue[256];
int taskCount = 0;
pthread_mutex_t mutexQueue;
pthread_cond_t condQueue;
void executeTask(Task* task) {
usleep(50000);
int result = task->a + task->b;
printf("The sum of %d and %d is %d\n", task->a, task->b, result);
}
void submitTask(Task task) {
pthread_mutex_lock(&mutexQueue);
taskQueue[taskCount] = task;
taskCount++;
pthread_mutex_unlock(&mutexQueue);
pthread_cond_signal(&condQueue);
}
// 1 2 3 4 5
// 2 3 4 5
void* startThread(void* args) {
while (1) {
Task task;
pthread_mutex_lock(&mutexQueue);
while (taskCount == 0) {
pthread_cond_wait(&condQueue, &mutexQueue);
}
task = taskQueue[0];
int i;
for (i = 0; i < taskCount - 1; i++) {
taskQueue[i] = taskQueue[i + 1];
}
taskCount--;
pthread_mutex_unlock(&mutexQueue);
executeTask(&task);
}
}
int main(int argc, char* argv[]) {
pthread_t th[THREAD_NUM];
pthread_mutex_init(&mutexQueue, NULL);
pthread_cond_init(&condQueue, NULL);
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_create(&th[i], NULL, &startThread, NULL) != 0) {
perror("Failed to create the thread");
}
}
srand(time(NULL));
for (i = 0; i < 100; i++) {
Task t = {
.a = rand() % 100,
.b = rand() % 100
};
submitTask(t);
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join the thread");
}
}
pthread_mutex_destroy(&mutexQueue);
pthread_cond_destroy(&condQueue);
return 0;
}
29. Thread Pools with function pointers in C
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define THREAD_NUM 4
typedef struct Task {
void (*taskFunction)(int, int);
int arg1, arg2;
} Task;
Task taskQueue[256];
int taskCount = 0;
pthread_mutex_t mutexQueue;
pthread_cond_t condQueue;
void sum(int a, int b) {
usleep(50000);
int sum = a + b;
printf("Sum of %d and %d is %d\n", a, b, sum);
}
void product(int a, int b) {
usleep(50000);
int prod = a * b;
printf("Product of %d and %d is %d\n", a, b, prod);
}
void executeTask(Task* task) {
task->taskFunction(task->arg1, task->arg2);
// usleep(50000);
// int result = task->a + task->b;
// printf("The sum of %d and %d is %d\n", task->a, task->b, result);
}
void submitTask(Task task) {
pthread_mutex_lock(&mutexQueue);
taskQueue[taskCount] = task;
taskCount++;
pthread_mutex_unlock(&mutexQueue);
pthread_cond_signal(&condQueue);
}
void* startThread(void* args) {
while (1) {
Task task;
pthread_mutex_lock(&mutexQueue);
while (taskCount == 0) {
pthread_cond_wait(&condQueue, &mutexQueue);
}
task = taskQueue[0];
int i;
for (i = 0; i < taskCount - 1; i++) {
taskQueue[i] = taskQueue[i + 1];
}
taskCount--;
pthread_mutex_unlock(&mutexQueue);
executeTask(&task);
}
}
int main(int argc, char* argv[]) {
pthread_t th[THREAD_NUM];
pthread_mutex_init(&mutexQueue, NULL);
pthread_cond_init(&condQueue, NULL);
int i;
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_create(&th[i], NULL, &startThread, NULL) != 0) {
perror("Failed to create the thread");
}
}
srand(time(NULL));
for (i = 0; i < 100; i++) {
Task t = {
.taskFunction = i % 2 == 0 ? &sum : &product,
.arg1 = rand() % 100,
.arg2 = rand() % 100
};
submitTask(t);
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join the thread");
}
}
pthread_mutex_destroy(&mutexQueue);
pthread_cond_destroy(&condQueue);
return 0;
}
Source:
Last updated