可以通过引用 传递参与另一个线程中运行的函数的参数。
是否可以返回来自另一个线程中运行的函数的结果,引用。如果是这样,怎么样?
答案 0 :(得分:3)
可以将参数传递给在另一个函数中运行的函数 线程,通过引用。
不直接,因为所有参数都被复制或移动到另一个线程中,但您可以模拟使用std::ref
或std::cref
传递的引用。见std::thread
constructor documentation:
通过值移动或复制线程函数的参数。如果 一个引用参数需要传递给线程函数,它有 被包裹(例如
std::ref
或std::cref
)。
当然,在使用它完成另一个线程之前,你必须确保引用的对象没有被破坏。
这是一个小例子:
#include <iostream>
#include <thread>
void f(int& x)
{
std::cout << x << '\n';
}
int main()
{
int a = 1;
std::thread t(f, std::ref(a));
t.join();
// safe, because `a` still exists at this point,
// but the thread is already finished
}
是否可以从另一个函数中运行的函数返回结果 线程,通过引用。
没有
首先,这没有意义,因为如果调用者被阻塞等待被调用的函数返回,它将失败线程的目的(但是,见下文)。
其次,这不是线程的工作方式。正如C ++标准所述,§4.7/ 1 [intro.multithread]
:
当一个线程创建另一个线程时,初始调用顶层 新线程的功能由新线程执行,而不是由新线程执行 创建线程。
换句话说,每个线程都有“自己的堆栈”。这与在同一个线程中使用函数完全不同。您不能使用return
将任何内容从新线程返回到原始线程。
您通过原始线程可访问的其他线程设置数据间接“返回”某些内容。如果您愿意,可以通过模拟参考来实现:
#include <iostream>
#include <thread>
void f(int& x, int& result)
{
result = x * x;
}
int main()
{
int a = 2;
int result;
std::thread t(f, std::ref(a), std::ref(result));
t.join();
std::cout << result << '\n';
}
除了这些玩具示例之外,共享数据更真实地是std::atomic
或由std::mutex
/ std::scoped_lock
等人保护。
话虽如此,你一定要看看std::future
。期货不会改变线程在内部的工作方式,但它们提供了一个类似普通函数调用堆栈的抽象层。
答案 1 :(得分:-1)
是的,但要非常小心,因为每个线程可能使用相同的资源并导致“数据竞争”。你应该使用“互斥”或其他机制来进行系统化 例如:没有互斥锁
#include<iostream>
#include<string>
#include<vector>
#include<thread>
static std::vector<std::string> glm;
void addMap(std::vector<std::string> &glm, std::string name)
{
glm.push_back(name);
std::cout << "Add: " << name << "\n";
}
int main()
{
std::thread t[4];
std::vector < std::string> names = { "Hellen", "Peter", "Bob", "Zoe" };
for(int i = 0; i < names.size(); i++)
{
t[i] = std::thread(addMap, glm, names[i]);
}
for(int i = 0; i < names.size(); i++)
{
t[i].join();
}
}
如上所示,我们预计会打印出来: 添加:海伦 添加:彼得 添加:鲍勃 添加:Zoe
但事实并非如此。有时,它会打印不够的名称,有时订单会有所不同。 使用互斥锁的示例:
#include<iostream>
#include<string>
#include<vector>
#include<thread>
#include<mutex>
static std::vector<std::string> glm;
std::mutex mut;
void addMap(std::vector<std::string> &glm, std::string name)
{
mut.lock();
glm.push_back(name);
std::cout << "Add: " << name << "\n";
mut.unlock();
}
int main()
{
std::thread t[4];
std::vector < std::string> names = { "Hellen", "Peter", "Bob", "Zoe" };
for(int i = 0; i < names.size(); i++)
{
t[i] = std::thread(addMap, glm, names[i]);
}
for(int i = 0; i < names.size(); i++)
{
t[i].join();
}
}
使用多线程编码时要非常小心