由一个线程初始化

在大多数情况下,应该在创建线程之前初始化多个线程访问的所有数据。这可确保所有线程都以清除状态启动,并且不会发生竞争条件

如果不可能,可以使用 once_flagcall_once

#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;
}

once_flag 用于协调可能想要初始化相同数据 Big 的不同线程。对 call_once 的调用保证了这一点

  • initBig 恰好被称为一次
  • call_once 阻止,直到通过相同或另一个线程调用 initBig

除了分配之外,在这种一次调用的函数中,典型的事情是分别使用 mtx_initcnd_init 对静态初始化的线程控制数据结构(如 mtx_tcnd_t)进行动态初始化。