C++中的thread最全用法归纳

基本 std::thread 的用法

最简单的 std::thread 范例如下所示,调用 thread 将立即同时开始执行这个新建立的线程之后 main() 的主线程也会继续执行,基本上这就是一个基本的建立多线程的功能,详细说明请看后面的范例。

#include <iostream>
#include <thread>

void myfunc() {
    std::cout << "myfunc\n";
    // do something ...
}

int main() {
    std::thread t1(myfunc);
    t1.join();
    return 0;
}

std::thread 常用的成员函数

以下为 c++ std::thread 常用的成员函数

  • get_id(): 取得目前的线程 id,回传一个为 std::thread::id 的类型
  • joinable(): 检查是否可join
  • join(): 等待线程完成
  • detach(): 与该线程分离,一旦该线程执行完后它所分配的资源会被释放
  • native_handle(): 取得平台原生的native handle

其他相关的常用函数有

  • sleep_for(): 停止目前线程一段指定的时间
  • yield(): 暂时放弃CPU一段时间,让给其它线程

范例1. 建立新 thread 执行函数

以下例子为建立新 c++ thread 来执行一个函数,其中 t1 是调用无参数的 foo() 函数,而 t2 线程是调用 bar() 有参数的函数

// g++ std-thread1.cpp -o a.out -std=c++11 -pthread
#include <iostream>
#include <thread>

void foo() {
    std::cout << "foo\n";
}

void bar(int x) {
    std::cout << "bar\n";
}

int main() {
    std::thread t1(foo); // 建立一个新线程且执行 foo 函数
    std::thread t2(bar, 0); // 建立一個新线程且执行 bar 函数
    std::cout << "main, foo and bar now execute concurrently...\n"; // synchronize threads

    std::cout << "sleep 1s\n";
    std::this_thread::sleep_for(std::chrono::seconds(1));

    std::cout << "join t1\n";
    t1.join(); // 等待 t1 线程结束
    std::cout << "join t2\n";
    t2.join(); // 等待 t2 线程结束

    std::cout << "foo and bar completed.\n";

    return 0;
}

输出

main, foo and bar now execute concurrently...
foo
bar
sleep 1s
join t1
join t2
foo and bar completed.

注意!在多线程中常常会互相对某函数或变量进行操作,需要对这些进行上锁,下一期将介绍,以确保同一时间只有某一个线程能进行存取

范例2. 建立新 thread 来执行一个类别中的函数

c++ std::thread 的构建可以传入 class 类别中的函数,如下范例所示

AA::start 分别建立 t1、t2 两个线程,而 t1 传入 AA::a1 类别函数,AA::a1 前面记得要加上&第二参数代表的是哪个类别,之后的参数为传入函数所需的参数

// g++ std-thread2.cpp -o a.out -std=c++11 -pthread
#include <iostream>
#include <thread>

class AA {
public:
    void a1() {
        std::cout << "a1\n";
    }

    void a2(int n) {
        std::cout << "a2 " << n << "\n";
    }

    void start() {
        std::thread t1(&AA::a1, this);
        std::thread t2(&AA::a2, this, 10);

        t1.join();
        t2.join();
    }
};

int main() {
    AA a;
    a.start();

    return 0;
}

输出

a1
a2 10

范例3. 建立新 thread 来执行 lambda expression

std::thread 的构建也可以传入 lambda expression,如下范例所示

auto f = [](int n) {
    // Do Something
};
std::thread t1(f, 3);

也可以写成

std::thread t1([](int n) {
    // Do Something
};, 3);

范例4. join 等待 thread 执行结束

在 main 主线程建立 t1 线程后,主线程便继续往下执行,如果主线程需要等 t1 执行完毕后才能继续执行的话就需要使用 join,即等待 t1 线程执行完 foo 后主先线程才能继续执行,否则主线程会一直阻塞在 join 这一行

#include <iostream>
#include <thread>
#include <chrono>

void foo() {
    this_thread::sleep_for(chrono::milliseconds(200));
    cout<<"foo";
}

int main() {
    std::thread t1(foo);
    cout<<"main 1";
    t1.join();
    cout<<"main 2";
    return 0;
}

范例5. detach 不等待 thread 执行结束

承上例,如果主线程不想等或是可以不用等待 t1 线程的话。就可以使用 detach 来让 t1 线程分离,接着主线程就可以继续执行,t1线程也在继续执行,在整个程序结束前最好养成好习惯确保所有子线程都已执行完毕,因为在 linux 系统如果主线程执行结束还有子线程在执行的话会报错

#include <iostream>
#include <thread>
#include <chrono>

void foo() {
    this_thread::sleep_for(chrono::milliseconds(200));
    cout<<"foo";
}

int main() {
    std::thread t1(foo);
    cout<<"main 1";
    t1.detach();
    cout<<"main 2";
    return 0;
}

std::thread 用数组建立多个 thread

// g++ std-thread-array.cpp -o a.out -std=c++11 -pthread
#include <iostream>
#include <thread>

void foo(int n) {
    std::cout << "foo() " << n << "\n";
}

int main() {
    std::thread threads[3];

    for (int i = 0; i < 3; i++) {
        threads[i] = std::thread(foo, i);
    }

    for (int i = 0; i < 3; i++) {
        threads[i].join();
    }

    std::cout << "main() exit.\n";

    return 0;
}

输出

foo() 1
foo() 0
foo() 2
main() exit.

std::thread 用 vector 建立多个 thread

// g++ std-thread-vector.cpp -o a.out -std=c++11 -pthread
#include <iostream>
#include <thread>
#include <vector>

void foo(int n) {
    std::cout << "foo() " << n << std::endl;
}

int main() {
    std::vector<std::thread> threads;

    for (int i = 0; i < 3; i++) {
        threads.push_back(std::thread(foo, i));
    }

    for (int i = 0; i < 3; i++) {
        threads[i].join();
    }

    std::cout << "main() exit.\n";

    return 0;
}

std::thread 参数传递使用传引用的方法

定义一个myfunc,其参数传递方式为传引用

void myfunc(int& n) {
    std::cout << "myfunc n=" << n << "\n";
    n+=10;
}

希望建立另外一个线程去执行 myfunc,之后需要取得这个 myfunc 的运算结果,但建立线程时如果写 std::thread t1(myfunc, n);编译会出现错误,为什么会这样呢?

因为在 std::thread 的参数传递方式为传值要传参考的话需要透过 std::ref 来辅助达成,所以就会写成这样,myfunc 与 myfunc2 的参数传递方式不同,可以看看这两者之间的差异

// g++ std-thread3.cpp -o a.out -std=c++11 -pthread
#include <iostream>
#include <thread>
 
void myfunc(int& n) {
    std::cout << "myfunc n=" << n << "\n";
    n+=10;
}

void myfunc2(int n) {
    std::cout << "myfunc n=" << n << "\n";
    n+=10;
}
 
int main() {
    int n1 = 5;
    std::thread t1(myfunc, std::ref(n1));
    t1.join();
    std::cout << "main n1=" << n1 << "\n";
    
    int n2 = 5;
    std::thread t2(myfunc2, n2);
    t2.join();
    std::cout << "main n2=" << n2 << "\n";

    return 0;
}

输出

myfunc n=5
main n1=15
myfunc n=5
main n2=5

​下一期会教大家在多线程中使用 std::mutex进行上锁的用法与范例
std::mutex最全用法归纳

  • 13
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
引用:在C++11,通过引入<thread>头文件,可以使用std::thread类来创建和管理线程。std::thread类封装了线程的创建、调度和销毁等操作,使得多线程编程更加方便。 在引用的代码片段,main函数创建了一个包含5个线程的线程数组。然后使用for循环,对每个线程调用std::thread类的构造函数来创建线程。线程的执行函数是thread_task,并传递一个参数i+1。接下来,通过调用join()函数,等待每个线程执行完毕。最后,输出"All threads joined"表示所有线程都已经执行完毕。 在引用的代码片段,independentThread函数是一个独立的线程函数,它会在启动后等待2秒钟,然后输出"Exiting concurrent thread"。threadCaller函数是另一个线程函数,它会创建一个新的线程t,并将独立线程函数independentThread绑定到t上。然后,通过调用t.detach()将线程t分离,使得线程t的执行与主线程并行。在threadCaller函数,同时还有一个睡眠1秒的操作,并输出"Exiting thread caller"。最后,主函数main调用threadCaller函数,并在之后睡眠5秒钟。 综上所述,C++11的<thread>头文件和std::thread类提供了方便的多线程编程接口,可以通过创建和管理线程对象来实现并行执行的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [C++11(std::thread)](https://blog.csdn.net/wuchalilun/article/details/48160393)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [C++ thread用法总结(整理)](https://blog.csdn.net/sevenjoin/article/details/82187127)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啥都生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值