Difference between revisions of "Pthread"

From Teknologisk videncenter
Jump to: navigation, search
m (Using ps)
m (Using multiple threads)
Line 37: Line 37:
 
long counter;
 
long counter;
 
void * adder(void * data) {
 
void * adder(void * data) {
         for (int i=0; i < 1000000; i++)
+
         for (int i=0; i < 100000000; i++)
 
                 counter++;
 
                 counter++;
 
}
 
}
Line 77: Line 77:
 
Value of counter is 1081391
 
Value of counter is 1081391
 
</source>
 
</source>
 +
 
==Using mutexes==
 
==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.  
 
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.  

Revision as of 11:58, 14 February 2023

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 < 100000000; 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

Links