1. 程式人生 > >多線程如何優雅地初始化全局變量?

多線程如何優雅地初始化全局變量?

是的 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

多線程如何優雅地初始化全局變量?