从父线程继承全局值
Inherit global value from parent thread
子线程有没有办法从其父线程继承全局值?我知道静态线程局部变量的动态初始化:https://stackoverflow.com/a/23558302/3214670,但这不是真正的继承 - 在这个例子中,从线程内部创建的线程不会获得它们的父值,而是在 main 中设置的值。
所以我有如下所示的代码。谁能说出如何使子线程具有与其父线程相同的全局价值?
线程是这样创建的:
main thread
| |
t1 t2
| |
t11 t22
法典:
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <memory>
static int g = 1;
static thread_local int s = g;
std::mutex m;
void print(int i)
{
std::unique_lock<std::mutex> u(m);
std::cout << "thread " << i << " s = " << s << std::endl;
}
void bar(int i)
{
print(i);
}
void foo(int i)
{
print(i);
std::this_thread::sleep_for(std::chrono::seconds(2));
std::thread c(bar, 11*i);
c.join();
}
int main()
{
std::thread a(foo, 1);
std::this_thread::sleep_for(std::chrono::seconds(1));
g = 2;
std::thread b(foo, 2);
a.join();
b.join();
return 0;
}
输出:
thread 1 s = 1
thread 2 s = 2
thread 11 s = 2
thread 22 s = 2
我想要的输出是:
thread 1 s = 1
thread 2 s = 2
thread 11 s = 1
thread 22 s = 2
请注意,我不想将任何变量传递给线程,而是使用全局变量。
您所要求的是不可能的,原因很简单:线程之间没有父子关系。
有多种解决方法,例如自己构建这样的继承树,但这意味着您还必须维护此树。这意味着,无论何时启动线程,都必须在树中为新线程创建一个新条目,并且每当线程完成时,都必须删除相应的条目。这带来了一堆问题,因为首先你必须以线程安全的方式这样做(避免竞争条件)。其次,每次启动或停止线程时都必须这样做,这实际上意味着您必须调整线程启动的每个位置。其中一些地方甚至可能超出您的控制范围。或者,您可以尝试找到特定于操作系统的钩子来跟踪线程的创建和销毁,但C++本身并不能为您提供一个钩子。
总之,我建议你重新考虑你的设计。使用伪全局变量不仅是维护的噩梦,而且您的方法也难以实现。
办法添加新的thread_local
初始化样式,也没有内置的继承感或fork
感。
如果你自己编码,这是可能的。只是要注意同步。在子线程完成读取源值之前,父线程无法更改其源值。(这已经给thread_local
变量带来了问题:它们在访问时被延迟初始化,而不是在线程初始化时一次全部初始化。
早于thread_local
的一个习惯用法是将线程句柄与线程本地状态一起封装在类中。父线程对象可以在将克隆作为子线程启动之前,使用其复制构造函数简单地克隆自身。然后,在子项启动之前,所有状态都已准备就绪,因此无需同步。
在该习惯用法中,指向线程类的指针将传递给新的线程函数。目前尚不清楚为什么foo
不能接受指针参数;这是非常不寻常的。
在C++中,您有所有线程共享的普通全局变量,以及每个线程的本地thread_local变量。
您的请求在某种程度上是两者之间的混合:如果我理解正确,您希望在第一级使用每线程全局变量,但在第二级共享该变量。这简直是矛盾的,您当然可以编写符合您要求的代码,但不要使用您要求的工具。为了使这一点更加明显:就像要求一个全局变量,该变量仅对循环的奇数迭代是全局的。
但是,有不同的解决方案可以为您提供所需的结果。下面我为此目的对您的代码进行了一些更改:
不好的代码示例,使用全局提供所需的结果:
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <memory>
#include <atomic>
static std::atomic<int> g;
static thread_local int s = g;
std::mutex m;
void print(int i)
{
std::unique_lock<std::mutex> u(m);
std::cout << "thread " << i << " s = " << s << std::endl;
}
void bar(int i)
{
print(i);
}
void foo(int i)
{
print(i);
int myVal;
myVal= g;
std::this_thread::sleep_for(std::chrono::seconds(2));
g=myVal; // Not really good code anyway.
std::thread c(bar, 11*i);
c.join();
}
int main()
{
g=1;
std::thread a(foo, 1);
std::this_thread::sleep_for(std::chrono::seconds(1));
g = 2;
std::thread b(foo, 2);
a.join();
b.join();
return 0;
}
考虑到此解决方案是一个示例,肯定有改进要做。
我会向您推荐其他人已经做过的相同:将s
值作为参数传递给thread 11
并thread 22
- 为什么在全局范围内使用"extern int a"似乎不行?
- 继承函数的重载解析
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 继承期间显示未知行为的子类
- 当vector是tje全局变量时,c++中vector的内存管理
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 头文件-继承c++
- 如何创建一个空的全局类并在启动时实例化它
- 为什么在保护模式下继承升级不起作用
- 通过继承类使用来自不同命名空间的运算符
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 内联函数中具有内部链接的全局变量
- 混合组合和继承的C++问题
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 从类继承时,继承的类是否会通过父类重新定义继承的变量
- 为什么虚函数不能是静态的和全局的?
- 公共与私人继承
- C++:从全局函数调用继承的成员函数
- 从父线程继承全局值
- 全局类与继承的比较