多線程如何優雅地初始化全局變量?
阿新 • • 發佈:2018-09-22
是的 tex 如果 編譯 oid 線程 pthread.h null operation
需求場景
如果使用多線程,那麽幾乎都會用到全局變量,這時初始化全局變量的技巧就很重要了。
通常初始化全局變量時就是像下面這樣的,先判斷是否已經初始化過了,然後才去初始化。在單線程場景下,lazy初始化(就是用到時才初始化)一般是下面這樣寫的,這沒問題。但是多線程場景下就不能這樣寫了,我們要先給random_is_initialized
創建一個mutex
,否則這段代碼就問題大了。但是mutex
也得初始化吧?初始化又要創建一個mutex
來保證前一個mutex
能正常初始化,這就陷入死循環了。
static int random_is_initialized = 0; extern int initialize_random(); // 這個函數用來初始化全局變量 int random_function() { if (random_is_initialized == 0) { initialize_random(); random_is_initialized = 1; } ... /* Operations performed after initialization. */ }
POSIX提供了一個函數pthread_once
,很適合解決這種問題。它能保證只初始化一次全局變量,而且線程安全,開發起來就很方便了。使用方法參考下面的實現。
實現
#include <pthread.h> static pthread_once_t random_is_initialized = PTHREAD_ONCE_INIT; void initialize_random() { printf("this will be printed only once\n"); } void *random_function(void *none) { (void) pthread_once(&random_is_initialized, initialize_random); // xxx邏輯代碼 return NULL; } int main() { int ret = 0; pthread_t thread; //創建10個線程 for (int i = 0; i < 10; i++) { pthread_create(&thread, NULL, random_function, NULL); } return 0; }
編譯 gcc -o test test.cpp -lpthread
你可能有疑問,為什麽不能在創建線程之前就初始化全局變量?那樣的話不需要考慮什麽線程安全。確實是的,但是如果有很多個全局變量呢(比如數組)?進程起來的時候就費很長時間去執行初始化的邏輯,太耗時間了,何不如選擇Lazy初始化。
參考
https://linux.die.net/man/3/pthread_once
多線程如何優雅地初始化全局變量?