由一個執行緒初始化

在大多數情況下,應該在建立執行緒之前初始化多個執行緒訪問的所有資料。這可確保所有執行緒都以清除狀態啟動,並且不會發生競爭條件

如果不可能,可以使用 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)進行動態初始化。