由一个线程初始化
在大多数情况下,应该在创建线程之前初始化多个线程访问的所有数据。这可确保所有线程都以清除状态启动,并且不会发生竞争条件。
如果不可能,可以使用 once_flag 和 call_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_init 或 cnd_init 对静态初始化的线程控制数据结构(如 mtx_t 或 cnd_t)进行动态初始化。