Threading in C/C++ programming language using pthreads
In this post, we will write a simple C script for performing a task concurrently using the POSIX pthread api in linux/unix like operating systems. For more details on concurrency, see my previous post about parallel computing in Python.
The one mental model
A thread is an independent flow of execution inside the same process — so threads share memory
(unlike separate processes). The two calls that matter: pthread_create spawns a worker thread
that runs alongside the main thread, and pthread_join makes the main thread wait for the
worker to finish before moving on.
anotherfunc(); pthread_join is why main waits for it to finish.Simple script to make use of the pthread api
#include <pthread.h> //pthread
#include <unistd.h> //sleep
#include <stdio.h> // printf
#include <string.h> //strcpy
struct sData {char text[100];};
void *myfunc(void *voidData) {
struct sData *data = voidData;
for (int i=0; i<8; i++) {
printf ("(i = %d) data text is %s \n", i, data->text);
sleep(1);
}
return NULL;
}
void anotherfunc() {
for (int i=0; i<3; i++) {
sleep(1); //sleep for 1s
printf("(i = %d) this is another func! \n", i);
}
}
int main() {
struct sData sd;
int tret;
pthread_t tid; // declare a new variable of type pthread_t tid to identify the thread in the system
strcpy(sd.text, "earthinversion");
tret = pthread_create(&tid, NULL, myfunc, &sd); // args: pointer to thread id, attributes, function name, arguments to this function
anotherfunc();
pthread_join(tid, NULL);
return 0;
}
In the main() function above, we define a data sd, and integer tret to store the output of the thread creation. We store text value in the sd.text, which will be argument for the myfunc. Then we create a variable tid of the data type pthread to identify the thread in the system. To create a thread, we need four arguments - pointer to the thread id, attributes (like detached state, scheduling policy, stack address, etc. Here, we specify it to be NULL, hence the default attributes will be used), name of the function and the argument to the function. Here, the function takes only one argument. If multiple arguments need to be given, then we need to use struct.
We then execute function anotherfunc() in the main thread. Since, the function anotherfunc() will finish before myfunc, we need to wait for the myfunc. To do this, we call the pthread_join. The second argument of the pthread_join is the return value of the thread. In this case, we declare it to be NULL.
Compilation
To compile the codes, we need to use the compiler with pthread library.
gcc threading.c -o threading
Add -pthread. To link the threading library and set up thread-safe compilation, the portable,
correct command is gcc threading.c -o threading -pthread. Without it you may hit an
undefined reference to pthread_create link error. (On very recent glibc, 2.34+, the pthread symbols
were merged into libc so it can link without the flag — but keep -pthread for portability.)
When you execute the threading, you should get similar return:
(i = 0) data text is earthinversion
(i = 1) data text is earthinversion
(i = 0) this is another func!
(i = 2) data text is earthinversion
(i = 1) this is another func!
(i = 3) data text is earthinversion
(i = 2) this is another func!
(i = 4) data text is earthinversion
(i = 5) data text is earthinversion
(i = 6) data text is earthinversion
(i = 7) data text is earthinversion
Notice how the two functions’ lines are interleaved — that’s the concurrency: while the worker
thread prints its 8 lines, the main thread is running anotherfunc() at the same time. Once
anotherfunc() returns, pthread_join blocks main until the worker’s remaining iterations finish.
What would happen if you removed the pthread_join(tid, NULL) line?
Recap
Without scrolling up — what’s the threading pattern?
- A thread runs concurrently inside the same process and shares memory with it.
pthread_create(&tid, NULL, fn, arg)launches a worker runningfn(arg)(bundle multiple args in astruct).- The main thread keeps going (here,
anotherfunc()), so output interleaves. pthread_join(tid, NULL)waits for the worker to finish beforemainreturns.- Compile with
gcc file.c -o out -pthread.
Further reads
- Thread functions in C/C++ — GeeksforGeeks.
Disclaimer of liability
The information provided by the Earth Inversion is made available for educational purposes only.
Whilst we endeavor to keep the information up-to-date and correct. Earth Inversion makes no representations or warranties of any kind, express or implied about the completeness, accuracy, reliability, suitability or availability with respect to the website or the information, products, services or related graphics content on the website for any purpose.
UNDER NO CIRCUMSTANCE SHALL WE HAVE ANY LIABILITY TO YOU FOR ANY LOSS OR DAMAGE OF ANY KIND INCURRED AS A RESULT OF THE USE OF THE SITE OR RELIANCE ON ANY INFORMATION PROVIDED ON THE SITE. ANY RELIANCE YOU PLACED ON SUCH MATERIAL IS THEREFORE STRICTLY AT YOUR OWN RISK.
Leave a comment