C++中线程的简单示例

Simple example of threading in C++

本文关键字:简单 线程 C++      更新时间:2023-10-16

有人能发布一个在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::thread的信息,点击这里

  • 在GCC上,使用-std=c++0x -pthread进行编译
  • 这应该适用于任何操作系统,前提是您的编译器支持此(C++11)功能

从技术上讲,任何这样的对象最终都将在C风格的线程库上构建,因为C++只是在C++0x中指定了一个库存std::thread模型,该模型刚刚确定,尚未实现。

这个问题有点系统性。从技术上讲,现有的C++内存模型不够严格,无法为所有"发生之前"的情况提供定义良好的语义。Hans Boehm不久前写了一篇关于这个主题的论文,并在制定这个主题的C++0x标准方面发挥了重要作用。

线程不能作为库实现

也就是说,有几个跨平台线程C++库在实践中运行得很好。英特尔线程构建块包含一个非常接近C++0x标准的tbb::thread对象,Boost有一个执行相同操作的Boost::thread库。

  • oneAPI线程构建块

  • 第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);
}

还有一个用于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编译。

POSIX线程

当搜索一个在新线程中调用自己的实例方法的C++类的示例时,会出现这个问题,但我们无法以这种方式使用这些答案中的任何一个。这里有一个这样做的例子:

h级

class DataManager
{
public:
    bool hasData;
    void getData();
    bool dataAvailable();
};

.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
    }
}

注意,这个例子没有涉及互斥或锁定。

除非需要在全局命名空间中有一个单独的函数,否则我们可以使用lambda函数来创建线程。

使用lambda创建线程的一个主要优点是,我们不需要将本地参数作为参数列表传递。我们可以使用相同的捕获列表,lambda的闭包属性将负责生命周期。

这是示例代码:

int main() {
    int localVariable = 100;
    thread th { [=]() {
        cout << "The value of local variable => " << localVariable << endl;
    }};
    th.join();
    return 0;
}

到目前为止,我发现C++lambdas是创建线程的最佳方式,尤其是对于更简单的线程函数。

这在很大程度上取决于您决定使用的库。例如,如果您使用wxWidgets库,那么线程的创建将如下所示:

class RThread : public wxThread {
public:
    RThread()
        : wxThread(wxTHREAD_JOINABLE){
    }
private:
    RThread(const RThread &copy);
public:
    void *Entry(void){
        //Do...
        return 0;
    }
};
wxThread *CreateThread() {
    //Create thread
    wxThread *_hThread = new RThread();
    //Start thread
    _hThread->Create();
    _hThread->Run();
    return _hThread;
}

如果您的主线程调用CreateThread方法,您将创建一个新线程,该线程将开始执行您的";条目";方法在大多数情况下,你必须保留对线程的引用才能加入或停止它

更多信息请参阅wxThread文档。