Ricerca…


Discussione semplice senza argomenti

Questo esempio di base conta a velocità diverse su due thread che chiamiamo sync (main) e async (new thread). Il thread principale conta 15 a 1Hz (1s) mentre il secondo conta a 10 a 0.5Hz (2s). Poiché il thread principale termina prima, usiamo pthread_join per farlo attendere async to finish.

#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

/* This is the function that will run in the new thread. */
void * async_counter(void * pv_unused) {
    int j = 0;
    while (j < 10) {
        printf("async_counter: %d\n", j);
        sleep(2);
        j++;
    }

    return NULL;
}

int main(void) {
    pthread_t async_counter_t;
    int i;
    /* Create the new thread with the default flags and without passing
     * any data to the function. */
    if (0 != (errno = pthread_create(&async_counter_t, NULL, async_counter, NULL))) {
        perror("pthread_create() failed");
        return EXIT_FAILURE;
    }

    i = 0;
    while (i < 15) {
        printf("sync_counter: %d\n", i);
        sleep(1);
        i++;
    }

    printf("Waiting for async counter to finish ...\n");

    if (0 != (errno = pthread_join(async_counter_t, NULL))) {
        perror("pthread_join() failed");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

Copiato da qui: http://stackoverflow.com/documentation/c/3873/posix-threads/13405/simple-thread-without-arguments dove inizialmente era stato creato da M. Rubio-Roy .

Semplice utilizzo di mutex

La libreria di thread POSIX fornisce l'implementazione della primitiva mutex, utilizzata per l'esclusione reciproca. Mutex viene creato usando pthread_mutex_init e distrutto usando pthread_mutex_destroy . Ottenere un mutex può essere fatto usando pthread_mutex_lock o pthread_mutex_trylock , (a seconda se si desidera il timeout) e il rilascio di un mutex avviene tramite pthread_mutex_unlock .

Segue un semplice esempio che utilizza un mutex per serializzare l'accesso alla sezione critica. Innanzitutto, l'esempio senza usare un mutex. Si noti che questo programma ha una corsa di dati dovuta all'accesso non sincronizzato a global_resource da parte dei due thread. Di conseguenza, questo programma ha un comportamento non definito :

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

// Global resource accessible to all threads
int global_resource;

// Threading routine which increments the resource 10 times and prints
// it after every increment
void* thread_inc (void* arg)
{
    for (int i = 0; i < 10; i++)
    {
        global_resource++;
        printf("Increment: %d\n", global_resource);
        // Make this thread slower, so the other one
        // can do more work
        sleep(1);
    }

    printf("Thread inc finished.\n");

    return NULL;
}

// Threading routine which decrements the resource 10 times and prints
// it after every decrement
void* thread_dec (void* arg)
{
    for (int i = 0; i < 10; i++)
    {
        global_resource--;
        printf("Decrement: %d\n", global_resource);
    }

    printf("Thread dec finished.\n");

    return NULL;
}

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

    if (0 != (errno = pthread_create(&threads[0], NULL, thread_inc, NULL)))
    {
        perror("pthread_create() failed");
        return EXIT_FAILURE;
    }

    if (0 != (errno = pthread_create(&threads[1], NULL, thread_dec, NULL)))
    {
        perror("pthread_create() failed");
        return EXIT_FAILURE;
    }

    // Wait for threads to finish
    for (int i = 0; i < 2; i++)
    {
        if (0 != (errno = pthread_join(threads[i], NULL))) {
            perror("pthread_join() failed");
            return EXIT_FAILURE;
        }
    }

    return EXIT_SUCCESS;
}

Un possibile risultato è:

Increment: 1
Decrement: 0
Decrement: -1
Decrement: -2
Decrement: -3
Decrement: -4
Decrement: -5
Decrement: -6
Decrement: -7
Decrement: -8
Decrement: -9
Thread dec finished.
Increment: -8
Increment: -7
Increment: -6
Increment: -5
Increment: -4
Increment: -3
Increment: -2
Increment: -1
Increment: 0
Thread inc finished.

Ora, se vogliamo sincronizzare questi thread in modo che vogliamo prima incrementare o decrementare completamente verso l'alto o verso il basso, e poi farlo in modo diverso, dobbiamo usare una primitiva di sincronizzazione, come mutex:

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

// Global resource accessible to all threads
int global_resource;
// Mutex protecting the resource
pthread_mutex_t mutex;

// Threading routine which increments the resource 10 times and prints
// it after every increment
void* thread_inc (void* arg)
{
    // Pointer to mutex is passed as an argument
    pthread_mutex_t* mutex = arg;

    // Execute the following code without interrupts, all the way to the
    // point B
    if (0 != (errno = pthread_mutex_lock(mutex)))
    {
        perror("pthread_mutex_lock failed");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < 10; i++)
    {
        global_resource++;
        printf("Increment: %d\n", global_resource);
        // Make this thread slower, so the other one
        // can do more work
        sleep(1);
    }

    printf("Thread inc finished.\n");

    // Point B:
    if (0 != (errno = pthread_mutex_unlock(mutex)))
    {
        perror("pthread_mutex_unlock failed");
        exit(EXIT_FAILURE);
    }

    return NULL;
}

// Threading routine which decrements the resource 10 times and prints
// it after every decrement
void* thread_dec (void* arg)
{
    // Pointer to mutex is passed as an argument
    pthread_mutex_t* mutex = arg;

    if (0 != (errno = pthread_mutex_lock(mutex)))
    {
        perror("pthread_mutex_lock failed");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < 10; i++)
    {
        global_resource--;
        printf("Decrement: %d\n", global_resource);
    }

    printf("Thread dec finished.\n");

    // Point B:
    if (0 != (errno = pthread_mutex_unlock(mutex)))
    {
        perror("pthread_mutex_unlock failed");
        exit(EXIT_FAILURE);
    }

    return NULL;
}

int main (int argc, char** argv)
{
    pthread_t threads[2];
    pthread_mutex_t mutex;

    // Create a mutex with the default parameters
    if (0 != (errno = pthread_mutex_init(&mutex, NULL)))
    {
        perror("pthread_mutex_init() failed");
        return EXIT_FAILURE;
    }

    if (0 != (errno = pthread_create(&threads[0], NULL, thread_inc, &mutex)))
    {
        perror("pthread_create() failed");
        return EXIT_FAILURE;
    }

    if (0 != (errno = pthread_create(&threads[1], NULL, thread_dec, &mutex)))
    {
        perror("pthread_create() failed");
        return EXIT_FAILURE;
    }

    // Wait for threads to finish
    for (int i = 0; i < 2; i++)
    {
        if (0 != (errno = pthread_join(threads[i], NULL))) {
            perror("pthread_join() failed");
            return EXIT_FAILURE;
        }
    }

    // Both threads are guaranteed to be finished here, so we can safely
    // destroy the mutex
    if (0 != (errno = pthread_mutex_destroy(&mutex)))
    {
        perror("pthread_mutex_destroy() failed");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

Una delle possibili uscite è

Increment: 1
Increment: 2
Increment: 3
Increment: 4
Increment: 5
Increment: 6
Increment: 7
Increment: 8
Increment: 9
Increment: 10
Thread inc finished.
Decrement: 9
Decrement: 8
Decrement: 7
Decrement: 6
Decrement: 5
Decrement: 4
Decrement: 3
Decrement: 2
Decrement: 1
Decrement: 0
Thread dec finished.

L'altro output possibile sarebbe inverso, nel caso che thread_dec ottenuto prima il mutex.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow