Skip to content

Instantly share code, notes, and snippets.

@insipx
Last active May 14, 2017 07:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save insipx/659a32552dfb271a06e75245ad6ac2a2 to your computer and use it in GitHub Desktop.
Save insipx/659a32552dfb271a06e75245ad6ac2a2 to your computer and use it in GitHub Desktop.
// Here's an example of using a Mutex to protect a value accross threads
/*
TL;DR
- You initialize a Mutex with PTHREAD_MUTEX_INITALIZER
- you can pass it around as a pointer just like anything else
- on write, lock
- read needs no lock
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUM_THREADS 5
//just a shared struct
//since can't pass multiple things to thread
typedef struct shared_vals {
int threadid;
int a;
int b;
pthread_mutex_t* access;
} shared_t;
void *some_work(void *shared)
{
shared_t *shared_type = (shared_t*)shared;
pthread_mutex_t access_local = *shared_type->access;
printf("Hey, I'm some thread!\n");
//writing needs a lock
pthread_mutex_lock(&access_local);
shared_type->a += 1;
pthread_mutex_unlock(&access_local);
//reading needs no lock
if(shared_type->a % 2 == 0) {
pthread_mutex_lock(&access_local);
shared_type->b += 1; //assignment/write
pthread_mutex_unlock(&access_local);
}
printf("B is: %d and a is: %d\n", shared_type->b, shared_type->a);
pthread_exit(NULL);
}
// what not to do
// Deadlock
// weird stuff might happen
/*
void *some_work(void *shared)
{
shared_t *shared_type = (shared_t*)shared;
pthread_mutex_t access_local = *shared_type->access;
printf("Hey, I'm some thread!\n");
//writing needs a lock
pthread_mutex_lock(&access_local); //locking without unlocking might cause a deadlock
shared_type->a += 1;
//reading needs no lock
if(shared_type->a % 2 == 0) {
shared_type->b += 1; //won't cause a deadlock, but an unsafe read/write
}
printf("B is: %d and a is: %d\n", shared_type->b, shared_type->a);
pthread_exit(NULL);
}
*/
int main()
{
pthread_t threads[NUM_THREADS];
//whenever you initialize a mutex, you basically just want to use this
pthread_mutex_t shared_val = PTHREAD_MUTEX_INITIALIZER;
// calloc is basically the same as malloc except sets all memory to 0, so no junk
shared_t *thread_info = calloc(1, sizeof(shared_t));
//Making the mutex a global would be simpler, but meh
thread_info->access = &shared_val;
thread_info->a = 4;
thread_info->b = 5;
int rc;
thread_info->a += 1; //increment once before sending it off to the threads
// threads haven't been started yet, so everything is OK
for(t=0;t<NUM_THREADS;t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, some_work, (void *)thread_info);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
sleep(5); // I think there is some way to ensure all threads are finished, but this is oK for the ex
printf("END\n");
printf("B is: %d and a is: %d\n", thread_info->b, thread_info->a);
free(thread_info);
// Last thing that main() should do
pthread_exit(NULL);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment