有人能发布一个在 C++ 中启动两个(面向对象的)线程的简单例子吗。
我正在寻找实际的 C++ 线程对象,可以在上面扩展运行方法(或类似方法),而不是调用 C 风格的线程库。
我没有提出任何特定于操作系统的要求,希望回答者能回复使用跨平台库。现在我明确说明一下。
有人能发布一个在 C++ 中启动两个(面向对象的)线程的简单例子吗。
我正在寻找实际的 C++ 线程对象,可以在上面扩展运行方法(或类似方法),而不是调用 C 风格的线程库。
我没有提出任何特定于操作系统的要求,希望回答者能回复使用跨平台库。现在我明确说明一下。
void task1(std::string msg)
{
std::cout << "task1 says: " << msg;
}
现在创建一个thread
对象,最终会调用上面的函数,像这样:
std::thread t1(task1, "Hello");
你需要包含 #include <thread>
才能访问 std::thread
类。
构造函数的第一个参数是线程将要执行的函数,后面跟着函数的参数。线程在构造时自动启动。
如果稍后需要等待线程执行完毕,可以调用:
t1.join();
加入线程意味着调用新线程的线程将等待新线程完成执行,然后才会继续自己的执行。
#include <string>
#include <iostream>
#include <thread>
using namespace std;
// The function we want to execute on the new thread.
void task1(string msg)
{
cout << "task1 says: " << msg;
}
int main()
{
// Constructs the new thread and runs it. Does not block execution.
thread t1(task1, "Hello");
// Do other things...
// Makes the main thread wait for the new thread to finish execution, therefore blocks its own execution.
t1.join();
}
-std=c++0x -pthread
进行编译。-std=c++0x
(而不是-std=c++0x
)”我相信第二个"c++0x"应该改为"c++11",但由于编辑太小,无法更改。 - zentrunixtask1
。因此,函数指针也由 task1
表示。但是感谢您提出这个问题,因为我认为我错了,它等同于 &task1
,所以无论您选择哪种形式编写都没有关系(如果是这样,我猜函数的指针是 &&task1
-- 那将是不好的)。相关问题。 - MasterMastic技术上,任何这样的对象最终都将在C风格线程库上构建,因为C++仅在C++0x中指定了一个标准的std::thread
模型,该模型刚刚被确定下来,尚未实施。
问题有些系统性。技术上,现有的C++内存模型不够严格,无法为所有“发生在之前”情况定义明确的语义。Hans Boehm曾在此问题上撰写了一篇论文,并在制定C++0x标准方面起到了重要作用。
话虽如此,实际上有几个跨平台的C++线程库可以很好地工作。Intel线程构建块包含一个tbb::thread对象,它与C++0x标准非常接近,Boost有一个boost::thread库也是如此。
oneAPI Threading Building Blocks(一个用于并行编程的C++库)
第19章 线程(Boost文档)
使用boost::thread,你会得到类似以下的内容:
#include <boost/thread.hpp>
void task1() {
// do stuff
}
void task2() {
// do stuff
}
int main (int argc, char ** argv) {
using namespace boost;
thread thread_1 = thread(task1);
thread thread_2 = thread(task2);
// do other stuff
thread_2.join();
thread_1.join();
return 0;
}
#include <thread>
#include <iostream>
#include <vector>
using namespace std;
void doSomething(int id) {
cout << id << "\n";
}
/**
* Spawns n threads
*/
void spawnThreads(int n)
{
std::vector<thread> threads(n);
// spawn n threads:
for (int i = 0; i < n; i++) {
threads[i] = thread(doSomething, i + 1);
}
for (auto& th : threads) {
th.join();
}
}
int main()
{
spawnThreads(10);
}
class DataManager
{
public:
bool hasData;
void getData();
bool dataAvailable();
};
Class.cpp
#include "DataManager.h"
void DataManager::getData()
{
// perform background data munging
hasData = true;
// be sure to notify on the main thread
}
bool DataManager::dataAvailable()
{
if (hasData)
{
return true;
}
else
{
std::thread t(&DataManager::getData, this);
t.detach(); // as opposed to .join, which runs on the current thread
}
}
还有一个适用于POSIX操作系统的POSIX库。
检查兼容性:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>
void *task(void *argument){
char* msg;
msg = (char*)argument;
std::cout << msg << std::endl;
}
int main(){
pthread_t thread1, thread2;
int i1, i2;
i1 = pthread_create(&thread1, NULL, task, (void*) "thread 1");
i2 = pthread_create(&thread2, NULL, task, (void*) "thread 2");
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
使用-lpthread进行编译。
除非需要在全局命名空间中创建单独的函数,否则我们可以使用lambda函数来创建线程。
使用lambda创建线程的主要优点之一是,我们不需要将本地参数作为参数列表传递。我们可以使用捕获列表进行相同操作,lambda的闭包属性会处理生命周期。
以下是示例代码:
int main() {
int localVariable = 100;
thread th { [=]() {
cout << "The value of local variable => " << localVariable << endl;
}};
th.join();
return 0;
}
迄今为止,我发现C++ lambda表达式是创建线程的最佳方式,特别适用于较简单的线程函数。
[=]()
的解释是什么?它使用了哪个特性? - Peter Mortensen这在很大程度上取决于您决定使用的库。例如,如果您使用 wxWidgets 库,则创建线程将如下所示:
class RThread : public wxThread {
public:
RThread()
: wxThread(wxTHREAD_JOINABLE){
}
private:
RThread(const RThread ©);
public:
void *Entry(void){
//Do...
return 0;
}
};
wxThread *CreateThread() {
//Create thread
wxThread *_hThread = new RThread();
//Start thread
_hThread->Create();
_hThread->Run();
return _hThread;
}