c++ 如何保护数据对一个线程的初始化?

piv4azn7  于 2023-03-09  发布在  其他
关注(0)|答案(3)|浏览(106)

使用现代C++,什么是最好的方法来拥有由一个线程初始化的共享内存,第一个到达这一点,然后由多个线程读取?它需要尽可能地轻量级。

int *ptr = nullptr;

void parallel_work() {
    // this should only done by the first thread to this point
    ptr = init_ptr();

    // all threads read After ptr is set 
    do_with(ptr);
}

int main() {
    std::thread th0 { &parallel_work };
    std::thread th1 { &parallel_work };
    std::thread th2 { &parallel_work };
    parallel_work();
}

如果可以的话,我真的希望避免将代码的整个读取部分 Package 在mutex中。
PS:这不是static函数变量的用例,因为我将在程序的生命周期中创建许多这样的变量。

3b6akqbq

3b6akqbq1#

std::call_once正是这样做的。

int *ptr = nullptr;
std::once_flag flag;

void parallel_work() {
    std::call_once(&flag, []() {
        ptr = init_ptr();
    });

    do_with(ptr);
}

它甚至强制其他线程等待init_ptr完成,并进行同步以确保它们都看到ptr的初始化值。

2ul0zpep

2ul0zpep2#

如我所述,将ptr设置为局部静态变量。

int* get_ptr() {
  static int *ptr = init_ptr();
  return ptr;
}

void parallel_work() {
  // all threads read After ptr is set 
  do_with(get_ptr());
}
2uluyalo

2uluyalo3#

ScottMayer的单例就可以了,只需将statc对象放入一个函数即可:

result_t& single (){
    static result_t res{ /*initialization parameters*/};
    return res;
};

编译器通过一个隐藏的once_flag对象或类似的魔术来管理第一次调用ownin函数时的初始化。

相关问题