Pthreads
Pthreads
#pthreads
Table of Contents
About 1
Remarks 2
Examples 2
Installation or Setup 2
Introduction 5
Remarks 5
Examples 6
Introduction 8
Examples 8
Credits 11
About
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: pthreads
It is an unofficial and free pthreads ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official pthreads.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/ 1
Chapter 1: Getting started with pthreads
Remarks
This section provides an overview of what pthreads is, and why a developer might want to use it.
It should also mention any large subjects within pthreads, and link out to the related topics. Since
the Documentation for pthreads is new, you may need to create initial versions of those related
topics.
Examples
Installation or Setup
#include <pthread.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
pthread_t thread;
int createerror = pthread_create(&thread, NULL, threadfunction, NULL);
/*creates a new thread with default attributes and NULL passed as the argument to the start
routine*/
if (!createerror) /*check whether the thread creation was successful*/
{
pthread_join(thread, NULL); /*wait until the created thread terminates*/
return 0;
}
fprintf("%s\n", strerror(createerror), stderr);
return 1;
}
#include <stdio.h>
#include <pthread.h>
https://riptutorial.com/ 2
{
printf("I am thread #%d\n", *(int *)arg);
return NULL;
}
/* This makes the main thread wait on the death of t1 and t2. */
pthread_join(t1, NULL);
pthread_join(t2, NULL);
How to compile:
This prints:
I am thread #1
I am thread #2
In main thread
A pointer to a concrete data type, converted to void *, can be used to pass values to and return
results from the thread function.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct thread_args
{
int a;
double b;
};
struct thread_result
{
long x;
double y;
};
https://riptutorial.com/ 3
void *thread_func(void *args_void)
{
struct thread_args *args = args_void;
/* The thread cannot return a pointer to a local variable */
struct thread_result *res = malloc(sizeof *res);
res->x = 10 + args->a;
res->y = args->a * args->b;
return res;
}
int main()
{
pthread_t threadL;
struct thread_args in = { .a = 10, .b = 3.141592653 };
void *out_void;
struct thread_result *out;
return 0;
}
In many cases it is unnecessary to pass a return value in this way - for example, space in the
argument struct can also be used to return results, or a pointer to a shared data structure can be
passed to the thread and the results stored there.
https://riptutorial.com/ 4
Chapter 2: Conditional Variables
Introduction
Conditional variables are useful in cases where you want a thread to wait for something that
happens in another thread. For instance, in a producer/consumer scenario with one or or more
producing threads and one consuming thread, conditional variables can be used to signal the
consuming thread that new data is available.
Remarks
General process
With this scheme, no matter when the signalling and waiting threads are scheduled, the waiting
thread will never miss data (as in, it will never be stuck waiting forever with valid data ready). This
can be realized by manually trying to run through the steps for the signalling thread, recording the
states of the mutex, condition and state variables, for each of the steps in the waiting thread.
To facilitate the above process, it is required to call pthread_cond_wait() with the mutex locked.
When called, pthread_cond_wait() will then unlock the mutex before putting the thread to sleep,
and, just before returning for whatever reason, the mutex will be relocked. This also means that if
some other thread currently has the mutex locked, pthread_cond_wait() will wait for the mutex to be
unlocked, and until the waiting thread can actually acquire the mutex - it will contend on it together
https://riptutorial.com/ 5
with any other threads trying to lock the mutex at the same time.
Spurious wakeups
Also, it may seem as if the while loop waiting on the state variable could be substituted for a
simple if statement. However, the while loop is needed, as the Posix standard allows
pthread_cond_wait() to do so-called "spurious" wakeups during the wait, without actually being
signalled. Thus, the code needs to recheck the state variable to see if pthread_cond_wait() returned
due to actually being signalled, or due to one of these spurious wakeups.
Examples
Producer / consumer example
pthread_mutex_t queueMutex;
pthread_cond_t queueCond;
Queue queue;
void Initialize() {
//Initialize the mutex and the condition variable
pthread_mutex_init(&queueMutex, NULL);
pthread_cond_init(&queueCond, NULL);
}
void Producer() {
//First we get some new data
Data *newData = MakeNewData();
//Lock the queue mutex to make sure that adding data to the queue happens correctly
pthread_mutex_lock(&queueMutex);
//Signal the condition variable that new data is available in the queue
pthread_cond_signal(&queueCond);
void Consumer() {
https://riptutorial.com/ 6
}
//As we returned from the call, there must be new data in the queue - get it,
Data *newData = queue.front();
// - and remove it from the queue
queue.pop();
https://riptutorial.com/ 7
Chapter 3: Race condition in pthreads
Introduction
When writing multi-threaded applications, one of the most common problems experienced are
race conditions. So we document the How do you detect them? and How do you handle them?
Examples
Example: Consider will have two threads T1 and T2.
If the same variable/resource/memory location is accessible by multiple threads and at least of the
thread is changing the value of variable/resource/memory location, then Race Condition can
occurred. Because if a thread is changing the value of variable/resource/memory location and
another thread tries to read the same then it will not get the updated value.
Note: If all threads are just reading the variable/resource/memory location then Race Condition
will not occur.
#include <stdio.h>
#include <pthread.h>
int x= 0;
int main()
{
pthread_t t1, t2;
printf("Point 1 >> X is: %d\n", x);
https://riptutorial.com/ 8
The output on my screen is:
Your output will vary. But for sure it will not be 20,000,000. Since both Thread executing the same
loop and having global variable int x;
So final value of x in line Point 2 >> X is: 9925047 should be 20,000,000. But it is not so.
The state of x can be changed by another thread during the time between x is being read and
when it is written back.
Let's say a thread retrieves the value of x, but hasn't stored it yet. Another thread can also retrieve
the same value of x (because no thread has changed it yet) and then they would both be storing
the same value (x+1) back in x!
Example:
Thread 1: stores 8 in x
Thread 2: stores 8 in x
Race conditions can be avoided by employing some sort of locking mechanism before the code
that accesses the shared resource or mutual exclusion.
#include <stdio.h>
#include <pthread.h>
int x= 0;
//Create mutex
pthread_mutex_t test_mutex;
https://riptutorial.com/ 9
void* fun(void* in)
{
int i;
for ( i = 0; i < 10000000; i++ )
{
//Lock mutex before going to change variable
pthread_mutex_lock(&test_mutex);
x++;
//Unlock mutex after changing the variable
pthread_mutex_unlock(&test_mutex);
}
}
int main()
{
pthread_t t1, t2;
printf("Point 1 >> X is: %d\n", x);
//Initlize mutex
pthread_mutex_init(&test_mutex, NULL);
Note: Modified program, which is free from race condition error, will take much longe to execute.
Because there is overburden on mutex lock and unlock.
https://riptutorial.com/ 10
Credits
S.
Chapters Contributors
No
Race condition in
3 cse, Mohan
pthreads
https://riptutorial.com/ 11