多线程环境中静态变量的C++初始化

     2023-02-22     170

关键词:

【中文标题】多线程环境中静态变量的C++初始化【英文标题】:C++ Initialization of static variable in multithreaded environment 【发布时间】:2017-05-29 14:03:17 【问题描述】:

我正在努力寻找一种在 C++ 中初始化类的静态成员的正确方法。上下文是随机数生成。我想做的是为随机数生成创建一个类,并为每个线程创建一个引擎。

现在看起来像这样:

template<typename T, int MIN, int MAX>
class Rng 
 public:
  T operator()() 
    return get_random_number(omp_get_thread_num());
  

 private:
  static T get_random_number(int id);
;

template<typename T, int MIN, int MAX>
T msl::Rng<T, MIN, MAX>::get_random_number(int id) 
  static std::vector<std::mt19937> engines;
  static std::vector<std::uniform_real_distribution<T>> dists;

  if (engines.empty())  
    int threads = omp_num_threads();
    engines.reserve(threads);
    dists.reserve(threads);

    for (int i = 0; i < threads; ++i) 
      std::random_device rd;
      std::mt19937 engine(rd());
      engines.push_back(engine);
      std::uniform_real_distribution<T> unif(MIN, MAX);
      dists.push_back(unif);
    
  

  return dists[id](engines[id]);

我是这样使用它的:

int main()

Rng<double, 0, 10> rng;
auto init = rng();

int n = 100;
int a[n];

#pragma omp parallel for
  for(int i = 0; i < n; ++i)
    a[i] = rng();
  

现在我想摆脱 main 方法中的前期初始化(auto init = rng()),但我不想引入不必要的开销,即线程不应该相互等待等,因为目前初始化只完成一次(显然),但生成发生了很多次。

我尝试的一件事是添加一个 while 循环,这样只有在第一次运行时所有线程才等待主线程初始化引擎:

template<typename T, int MIN, int MAX>
T msl::Rng<T, MIN, MAX>::get_random_number(int id) 
  static std::vector<std::mt19937> engines;
  static std::vector<std::uniform_real_distribution<T>> dists;

  int threads = omp_num_threads();

#pragma omp master

  if (engines.empty())  
    engines.reserve(threads);
    dists.reserve(threads);

    for (int i = 0; i < threads; ++i) 
      // init stuff...
    
  


  while(engines.size() < threads)
    continue; 

  return dists[id](engines[id]);

但是,这只会导致死锁。解决这个问题的典型方法是什么?我还考虑了一个互斥锁和条件变量来唤醒线程,但由于锁定,这可能代价高昂,实际上只在第一次调用函数时才需要。

【问题讨论】:

如果你真的需要以这种方式结束,那么将有问题的变量设为static thread_local 【参考方案1】:

典型的方式是使用构造函数

Rng构造函数 执行这些类型的初始化。

这确实是它的工作。

目前还不清楚为什么你首先在这里有static 数据。 为什么不使用成员变量

【讨论】:

您好,这里的问题是Rng对象是在一个函数A中创建的,该函数A被传递给另一个函数B,该函数B执行了A多次。因此,使用构造函数进行初始化会产生过多的开销。但我没有想到的是,我可以将函数 A 中的 Rng 变量设为静态,或者我可以使用一个函子,该函子将 Rng 对象作为成员变量。谢谢你的提示。 :) “Rng 对象是在函数 A 中创建的,该函数 A 被传递给另一个函数 B,该函数 B 执行 A 多次” 这……很奇怪。 假设它就像 std::transform 并且 Rng 对象是在作为参数传递的函数中创建的,我不希望每次应用函数时都进行昂贵的初始化。 @F***:那么你在错误的函数中创建它。

C++ 多线程环境中的内存访问

】C++多线程环境中的内存访问【英文标题】:MemoryaccessinC++multithreadingenvironment【发布时间】:2017-07-2002:31:19【问题描述】:我有一个问题,即主线程中的函数被阻塞,直到在另一个线程中设置了局部变量。我用信号量来阻塞主线... 查看详情

java多线程并发问题

程序中的变量有一部分是成员变量,调用时会初始化,其他系统调用我的接口的时候,是多线程并发,问题是当线程A调用接口到一半的时候,线程B进入初始化了成员变量,这样在线程A结束返回报文的时候使用的成员变量就是过... 查看详情

C++ 中的静态变量

...所有单元。当在类中声明时,通常静态变量在.cpp文件中初始化吗?那么这是否意味着静态变量范围仅限于2个编译单元?【问题讨论】:“静态”关键字非常重载。在不同的地方有不同的意思。这就是为什么在面试中提出一个有... 查看详情

C++ 静态初始化顺序

】C++静态初始化顺序【英文标题】:C++staticinitializationorder【发布时间】:2010-11-0314:10:01【问题描述】:当我在C++中使用静态变量时,我经常想要初始化一个变量并将另一个变量传递给它的构造函数。换句话说,我想创建相互依... 查看详情

C++静态成员变量及其初始化

】C++静态成员变量及其初始化【英文标题】:C++staticmembervariableanditsinitialization【发布时间】:2011-05-3115:57:54【问题描述】:对于C++类中的静态成员变量-初始化在类外完成。我想知道为什么?对此有任何逻辑推理/限制吗?或者它... 查看详情

静态成员变量初始化 C++

】静态成员变量初始化C++【英文标题】:staticmembervariablesinitializationc++【发布时间】:2012-03-1621:25:00【问题描述】:为什么当我没有将值初始化为静态成员变量时编译器会给我一个错误?不应该初始化为0吗?为什么我必须在类外... 查看详情

c++面向对象的静态函数多线程调用

我想问下,我有两个线程调用同一份静态代码用不用加锁进行一下保护啊?比如:ClassA中定义staticintReadXX();.....我在线程Thread1中调用voidrun()while(1)intx=A::ReadXX();在Thread2线程中也调用voidrun()while(1)intc=A::ReadXX();在调研A::ReadXX()的时候... 查看详情

C++ - 在派生类中静态初始化基类受保护的成员变量

】C++-在派生类中静态初始化基类受保护的成员变量【英文标题】:C++-Initialisebaseclassprotectedmembervariablesstaticallyinderivedclass【发布时间】:2019-04-0312:30:50【问题描述】:我们正在尝试在我们的项目中使用有界primitivetypes,我们可以... 查看详情

java线程安全问题之静态变量实例变量局部变量

 java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同《java并发编程实践》中所说:写道给线程安全下定义比较困难。存在很多种定义,如:“一个类在可以被多个... 查看详情

多线程编程之windows环境下创建新线程

在Win32API中,创建线程的基本函数是CreateThread,而_beginthread(ex)是C++运行库的函数。为什么要有两个呢?因为C++运行库里面有一些函数使用了全局量,如果使用CreateThread的情况下使用这些C++运行库的函数,就会出现不安全的问题。... 查看详情

C++ 函数中静态变量的生命周期是多少?

...如果一个变量在函数的作用域中被声明为static,它只会被初始化一次并且在函数调用之间保持它的值。它的寿命究竟是多少?什么时候调用它的构造函数和析构函数?voidfoo()staticstringplonk="Whenwil 查看详情

如何在构造函数 C++ 中使用静态变量?

...中使用静态变量时遇到问题。我需要在构造函数的第一行初始化中设置两个等于零的值,但我不想在再次调用构造函数后将它们设置为零。这两个值将递增。因此,在了解了静态变量之后,我尝试在构造函数中使用静态变量,但... 查看详情

C++ 静态结构类型成员初始化

】C++静态结构类型成员初始化【英文标题】:C++StaticStructTypeMemberInitializations【发布时间】:2014-01-1112:53:32【问题描述】:可能重复:link大家好,关于静态成员变量,我不明白一件奇怪的事情。如果静态变量的“定义”(我不确... 查看详情

通过调用 C++ 中的静态类函数初始化全局静态变量

】通过调用C++中的静态类函数初始化全局静态变量【英文标题】:Globalstaticvariableinitialisedwithacalltostaticclassfunctioninc++【发布时间】:2017-04-0216:46:22【问题描述】:不确定问题的表述是否正确,但问题就在这里。我有一个静态库,... 查看详情

c++中静态成员变量(不支持在类定义中初始化不是常量的静态数据成员)(代码片段)

文章目录成员变量与静态成员变量几点说明成员变量与静态成员变量对象的内存中包含了成员变量,不同的对象占用不同的内存(已在《C++对象的内存模型》中提到),这使得不同对象的成员变量相互独立&#... 查看详情

c++面向对象-static、const

...ed、private来修饰达到局部共享的目的。static成员变量必须初始化,而且必须在类外面初始化,初始化时不能带static。静态成员由于是存在全局区,不会跟着对象销毁而释放,下面我们结合static函数来看下。静态成员函数内部不能... 查看详情

请问c++语言里静态变量和全局变量有啥区别?谢谢

...没有全局变量啊三楼说的意思是静态变量定义的时候就要初始化而且不能改??相当于一个常量??1.全局变量的作用域是整个项目,它只需要在一个源文件中定义就可以作用于所有的源文件,其它不包括全局变量定义的文件需... 查看详情

C++:OpenMP 中的私有静态变量

...静态变量和函数(来自模板化类)设为私有,以便在每个线程中具有不同的值?【问题讨论】:【参考方案1】:根据场景,你应该可以使用:#pragmaompthreadprivate(theVariable)有关详细信息,请参阅OpenMP中u 查看详情