Pthread
Contents
Using pthreads
Single thread example
The example below shows the syntax of pthreads. The thread doesn't do anything useful.
- compile with: gcc pt1.c -o pt -pthread
1 #include <stdio.h>
2 #include <pthread.h>
3
4 long counter;
5 void * adder(void * data) {
6 for (int i=0; i < 1000000; i++)
7 counter++;
8 }
9
10 int main(void) {
11 int i;
12 pthread_t pt;
13
14 counter=0;
15 pthread_create(&pt, NULL, adder, NULL);
16 pthread_join(pt, NULL);
17 printf("Value of counter is %ld\n", counter);
18 return(0);
19 }
When creating a pthread with pthread_create() resources are allocated in the running process for the thread. pthread_join() waits for the thread to finish and releases its resources.
Using multiple threads
Using multiple threads simultaneously can give race conditions as the code below shows when running.
1 #include <stdio.h>
2 #include <pthread.h>
3
4 #define THREADS 2
5
6 long counter;
7 void * adder(void * data) {
8 for (int i=0; i < 1000000; i++)
9 counter++;
10 }
11
12 int main(void) {
13 int i;
14 pthread_t pt[THREADS];
15
16 counter=0;
17
18 for (i=0; i < THREADS; i++) {
19 pthread_create(&pt[i], NULL, adder, NULL);
20 printf("Created thread %d\n",i+1);
21 }
22
23 for (i=0; i < THREADS; i++) {
24 pthread_join(pt[i], NULL);
25 printf("Joined thread %d\n",i+1);
26 }
27
28 printf("Value of counter is %ld\n", counter);
29 return(0);
30 }
Running the code two times gave this output as example:
- Note: The two wrong counter values.
heth@emb3:~/bin$ pt2
Created thread 1
Created thread 2
Joined thread 1
Joined thread 2
Value of counter is 1032119
heth@emb3:~/bin$ pt2
Created thread 1
Created thread 2
Joined thread 1
Joined thread 2
Value of counter is 1081391
Using mutexes
A Mutex or Mutual exclusion is a lock that can be owned by only thread at a time. When unlocked another thread can lock it.
#include <stdio.h>
#include <pthread.h>
#define THREADS 2
long counter;
pthread_mutex_t mutex;
void * adder(void * data) {
for (int i=0; i < 1000000; i++) {
pthread_mutex_lock(&mutex) ;
counter++;
pthread_mutex_unlock(&mutex);
}
}
int main(void) {
int i;
pthread_t pt[THREADS];
counter=0;
if (pthread_mutex_init(&mutex, NULL) != 0)
printf("Mutex init failed\n");
for (i=0; i < THREADS; i++) {
pthread_create(&pt[i], NULL, adder, NULL);
printf("Created thread %d\n",i+1);
}
for (i=0; i < THREADS; i++) {
pthread_join(pt[i], NULL);
printf("Joined thread %d\n",i+1);
}
printf("Value of counter is %ld\n", counter);
return(0);
}
The output from this example is accurate:
heth@emb3:~/bin$ pt1_mutex
Created thread 1
Created thread 2
Joined thread 1
Joined thread 2
Value of counter is 2000000
Releasing resources used by a pthread
To release the resources - memory for stack and householding - it is necessary to call either pthread_detach or pthread_join. The resources are not released when the pthread exits without one of these calls.
- pthread_join is called by the process or another thread.
- pthread_detach is typically called by the thread itself to release the resources when the thread terminates
See threads of a running process
Using ps
To see the thread ids - TID - of a running process use ps -T or filter as below
heth@emb3:~/bin/process-and-thread/thread$ ps -L xo pid,tid,cmd | grep -P '(pt2|CMD)'
PID TID CMD
3516974 3516974 ./pt2_mutex
3516974 3516975 ./pt2_mutex
3516974 3516976 ./pt2_mutex
3522329 3522329 grep --color=auto -P (pt2|CMD)
- NOTE
- Some confusion about thread ID - TID and other abbreviations - in the man page for ps the value of TID can also appear as lwp or spid