Suche…


Syntax

  • #ifndef __STDC_NO_THREADS__
  • # include <threads.h>
  • #endif
  • void call_once(once_flag *flag, void (*func)(void));
  • int cnd_broadcast(cnd_t *cond);
  • void cnd_destroy(cnd_t *cond);
  • int cnd_init(cnd_t *cond);
  • int cnd_signal(cnd_t *cond);
  • int cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx, const struct timespec *restrict ts);
  • int cnd_wait(cnd_t *cond, mtx_t *mtx);
  • void mtx_destroy(mtx_t *mtx);
  • int mtx_init(mtx_t *mtx, int type);
  • int mtx_lock(mtx_t *mtx);
  • int mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts);
  • int mtx_trylock(mtx_t *mtx);
  • int mtx_unlock(mtx_t *mtx);
  • int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
  • thrd_t thrd_current(void);
  • int thrd_detach(thrd_t thr);
  • int thrd_equal(thrd_t thr0, thrd_t thr1);
  • _Noreturn void thrd_exit(int res);
  • int thrd_join(thrd_t thr, int *res);
  • int thrd_sleep(const struct timespec *duration, struct timespec* remaining);
  • void thrd_yield(void);
  • int tss_create(tss_t *key, tss_dtor_t dtor);
  • void tss_delete(tss_t key);
  • void *tss_get(tss_t key);
  • int tss_set(tss_t key, void *val);

Bemerkungen

C11-Threads sind eine optionale Funktion. Ihre Abwesenheit kann mit __STDC__NO_THREAD__ getestet __STDC__NO_THREAD__ . Derzeit (Juli 2016) ist diese Funktion noch nicht von allen C-Bibliotheken implementiert, die ansonsten C11 unterstützen.

C-Bibliotheken, von denen bekannt ist, dass sie C11-Threads unterstützen, sind:

C-Bibliotheken, die noch keine C11-Threads unterstützen:

Starten Sie mehrere Threads

#include <stdio.h>
#include <threads.h>
#include <stdlib.h>

struct my_thread_data {
   double factor;
};

int my_thread_func(void* a) {
   struct my_thread_data* d = a;
   // do something with d
   printf("we found %g\n", d->factor);
   // return an success or error code
   return d->factor > 1.0;
}


int main(int argc, char* argv[argc+1]) {
    unsigned n = 4;
    if (argc > 1) n = strtoull(argv[1], 0, 0);
    // reserve space for the arguments for the threads
    struct my_thread_data D[n];     // can't be initialized
    for (unsigned i = 0; i < n; ++i) {
         D[i] = (struct my_thread_data){ .factor = 0.5*i, };
    }
    // reserve space for the ID's of the threads
    thrd_t id[4];
    // launch the threads
    for (unsigned i = 0; i < n; ++i) {
         thrd_create(&id[i], my_thread_func, &D[i]);
    }
    // Wait that all threads have finished, but throw away their
    // return values
    for (unsigned i = 0; i < n; ++i) {
         thrd_join(id[i], 0);
    }
    return EXIT_SUCCESS;
}

Initialisierung durch einen Thread

In den meisten Fällen sollten alle Daten, auf die mehrere Threads zugreifen, initialisiert werden, bevor die Threads erstellt werden. Dadurch wird sichergestellt, dass alle Threads mit einem eindeutigen Status beginnen und keine Race-Bedingung auftritt.

Wenn dies nicht möglich ist, können once_flag und call_once verwendet werden

#include <threads.h>
#include <stdlib.h>

// the user data for this example
double const* Big = 0;

// the flag to protect big, must be global and/or static
static once_flag onceBig = ONCE_INIT;

void destroyBig(void) {
   free((void*)Big);
}

void initBig(void) {
    // assign to temporary with no const qualification
    double* b = malloc(largeNum);
    if (!b) {
       perror("allocation failed for Big");
       exit(EXIT_FAILURE);
    }
    // now initialize and store Big
    initializeBigWithSophisticatedValues(largeNum, b);
    Big = b;
    // ensure that the space is freed on exit or quick_exit
    atexit(destroyBig);
    at_quick_exit(destroyBig);
}

// the user thread function that relies on Big
int myThreadFunc(void* a) {
   call_once(&onceBig, initBig);
   // only use Big from here on
   ...
   return 0;
}

Die once_flag wird verwendet , um verschiedene Themen zu koordinieren, die die gleichen Daten initialisieren möchten Big . Der Aufruf von call_once garantiert das

  • initBig wird genau einmal aufgerufen
  • call_once blockiert, bis ein solcher Aufruf von initBig vom selben oder einem anderen Thread erfolgt ist.

Typisch für eine solche einmal aufgerufene Funktion ist neben der Zuweisung die dynamische Initialisierung von Thread-Steuerungsdatenstrukturen wie mtx_t oder cnd_t , die nicht statisch mit mtx_init bzw. cnd_init initialisiert werden mtx_init .



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow