由一個執行緒初始化
在大多數情況下,應該在建立執行緒之前初始化多個執行緒訪問的所有資料。這可確保所有執行緒都以清除狀態啟動,並且不會發生競爭條件。
如果不可能,可以使用 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
)進行動態初始化。