多线程如何优雅地初始化全局变量?

Posted xcw0754

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程如何优雅地初始化全局变量?相关的知识,希望对你有一定的参考价值。

需求场景

如果使用多线程,那么几乎都会用到全局变量,这时初始化全局变量的技巧就很重要了。

通常初始化全局变量时就是像下面这样的,先判断是否已经初始化过了,然后才去初始化。在单线程场景下,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
");
}

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

以上是关于多线程如何优雅地初始化全局变量?的主要内容,如果未能解决你的问题,请参考以下文章

使用线程局部存储将具有全局变量的单线程遗留代码转换为多线程代码

如何优雅地停止长时间执行的线程?

并发设计模式 | 两阶段终止模式:如何优雅地终止线程?

线程同步

在编写RTOS代码时,如何设计一个简单优雅可拓展的任务初始化结构?

在编写RTOS代码时,如何设计一个简单优雅可拓展的任务初始化结构?