View on GitHub

Notes

reference notes

Pthreads

What is a Thread?

Definitions

Why Threads?

Threads and Memory

Targets for Threaded Programs

Shared-memory parallel systems

Shared Memory

Threaded Programming Models

Pthreads

Introduction

Threads Within A Unix Process

Why Pthreads?

Designing Threaded Programs

Parallel Programming

Threaded programs models

Shared Memory Model

Thread-safeness

Thread Limits

Thread Limits

Mutual Exclusion (Mutex)

Deadlock

The Pthreads API

grouped into four major groups:

Examples of Library Routines

Routine Prefix Functional Group
pthread_ Threads themselves and miscellaneous subroutines
pthread_attr_ Thread attributes objects
pthread_mutex_ Mutexes
pthread_mutexattr_ Mutex attributes objects
pthread_cond_ Condition variables
pthread_condattr_ Condition attributes objects
pthread_key_ Thread-specific data keys
pthread_rwlock_ Read/write locks
pthread_barrier_ Synchronization barriers

Creating and Terminating Threads

Creating Threads

Creating Threads:

Thread Attributes

Thread Binding and Scheduling

Terminating Threads & pthread_exit():

Sample Pthread program

#include <pthread.h>
#include <stdio.h>

#define NUM_THREADS 5

void *PrintHello(void *threadid) {
    long tid = (long) threadid;
    printf("Hello World! It's me, thread #%ld!\n", tid);
    pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
    int rc;
    long t;
    pthread_t threads[NUM_THREADS];// declare 5 threads
    
    for (t = 0; t < NUM_THREADS; t++) {
        printf("In main: creating thread %ld\n", t);
        rc = pthread_create(&threads[t], NULL, PrintHello, (void *) t); // create 5 threads
        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
        }
    }
    
    pthread_exit(NULL); // main thread exit
}

Sample Pthread program: Explanation

Thread management

Passing Arguments to Threads

Example 1 - Thread Argument Passing

long taskids[NUM_THREADS];
for (t = 0; t < NUM_THREADS; t++) {
    taskids[t] = t;
    printf("Creating thread %ld\n", t);
    rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskids[t]);
    // ...
}

This code fragment demonstrates how to pass a simple integer to each thread.

The calling thread uses a unique data structure for each thread, insuring that each thread’s argument remains intact throughout the program.

Example 2 - Thread Argument Passing

#include <stdio.h>
#include <pthread.h>

// Define the structure to hold thread data
struct thread_data {
    int thread_id;
    int sum;
    char *message;
};

#define NUM_THREADS 5

// Array to store thread data for each thread
struct thread_data thread_data_array[NUM_THREADS];

// Thread function
void *PrintHello(void *threadarg) {
    // Cast the argument back to a thread_data structure
    struct thread_data *my_data = (struct thread_data *)threadarg;
    
    // Extract data from the structure
    int taskid = my_data->thread_id;
    int sum = my_data->sum;
    char *hello_msg = my_data->message;
    
    // Perform thread-specific tasks
    // ...

    pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
    int rc;
    pthread_t threads[NUM_THREADS];

    // Populate thread_data_array with data for each thread
    for (int t = 0; t < NUM_THREADS; t++) {
        thread_data_array[t].thread_id = t;
        // Assign values to other fields in thread_data_array
        // e.g., thread_data_array[t].sum = ...;
        //      thread_data_array[t].message = ...;

        // Create a new thread and pass the corresponding thread_data structure as an argument
        rc = pthread_create(&threads[t], NULL, PrintHello, (void *)&thread_data_array[t]);
        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
        }
    }

    // Optionally, you can wait for the threads to finish using pthread_join

    pthread_exit(NULL);
}

This example shows how to setup/pass multiple arguments via a structure. Each thread receives a unique instance of the structure.

Example 3 - Thread Argument Passing (Incorrect)

In this example, the thread argument is passed incorrectly, using the address of a shared variable t. This example performs argument passing incorrectly. • It passes the address of variable t, which is shared memory space and visible to all threads. • As the loop iterates, the value of this memory location changes, possibly before the created threads can access it. • The result is that all threads may end up using the same value for their argument.

int rc;
long t;
for(t=0; t<NUM_THREADS; t++)
{
printf("Creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) &t);
...
}

Joining and Detaching Threads

Joining:

How to JOIN

Detaching

Mutex

What?

How?

Creating and Destroying Mutexes

Condition Variables