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