子线程是否有办法从其父线程继承全局值?我知道静态,线程局部变量的动态初始化:https://stackoverflow.com/a/23558302/3214670,但它没有真正的继承 - 在这个例子中,从线程内创建的线程不会得到它们的父值,而是值集在主要。
所以我有一个如下代码。任何人都可以告诉如何让子线程与父母具有相同的全球价值吗?
线程是这样创建的:
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
请注意,我不想将任何变量传递给线程,而是使用全局变量。
答案 0 :(得分:2)
由于一个简单的原因,你所要求的是不可能的:线程之间没有父子关系。
有多种解决方法,比如自己构建这样的继承树,但这意味着您还必须维护此树。这意味着无论何时启动线程,您都必须为树中的新线程创建新条目,并且每当线程完成时,您必须删除相应的条目。这提出了一系列问题,因为首先必须以线程安全的方式(避免竞争条件)这样做。其次,每次启动或停止线程时都必须这样做,这实际上意味着您必须调整线程启动的每个位置。其中一些地方甚至可能无法控制。或者,您可以尝试查找特定于操作系统的挂钩来跟踪线程创建和销毁,但C ++本身并不提供一个。
总之,我建议你重新考虑你的设计。伪全局变量的使用不仅是维护的噩梦,而且你的方法也难以实现。
答案 1 :(得分:1)
无法添加thread_local
初始化的新样式,并且没有内置的继承感或fork
。
如果您自己编码,这是可能的。请注意同步。在子线程完成读取之前,父线程无法更改其源值。 (这已经给thread_local
变量带来了问题:它们在访问时被懒惰地初始化,而不是在线程初始化时立即初始化。)
早于thread_local
的一个习惯用法是将线程句柄与线程局部状态一起封装在一个类中。在将克隆作为子项启动之前,父线程对象可以使用其复制构造函数简单地克隆自身。然后,在孩子开始之前所有状态都准备好了,因此不需要同步。
在那个习语中,指向线程类的指针将被传递给新的线程函数。目前尚不清楚为什么foo
不能采用指针参数;这很不寻常。
答案 2 :(得分:1)
在C ++中,您拥有所有线程共享的普通全局变量,以及本地每线程的thread_local变量。
你的请求在某种程度上是两者之间的混合:如果我理解正确,你需要第一级的每线程全局变量,但是它会在第二级共享。这简直是矛盾的,您当然可以制作符合您要求的代码,但不能使用您要求的工具。 为了使这一点更加明显:就像要求一个全局变量一样,它只是一个循环奇数迭代的全局变量。
但是,有不同的解决方案可以为您提供所需的结果。为此,我对您的代码进行了一些更改:
不是很好的代码示例,使用global来提供所需的结果:
#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