一文搞定c++多线程

本文详细介绍了C++11中的多线程支持,包括线程创建、detach与join的区别、线程同步以及解决竞争条件的方法。通过示例代码展示如何创建、管理和同步多线程,帮助开发者理解并掌握C++多线程编程。
摘要由CSDN通过智能技术生成

一文搞定c++多线程

c++11引入了用于多线程操作的thread类,该库移植性更高,并且使得写多线程变得简洁了一些。

多线程头文件支持

为了支持多线程操作,c++11新标准引入了一些头文件来支持多线程编程:

  • <thread>:内部声明了 std::thread 类,用于创建多线程
  • <atomic>:内部声明std::atomic 和 std::atomic_flag两个类,可以利用这两个类实现原子类型的各种特性,并且声明了一些原子操作函数
  • <mutex>:提供了多种互斥操作,可以显式避免数据竞争,内部包含mutex类型、lock类型以及功能函数.
  • <condition_variable>:声明了与条件变量相关的类,包括 std::condition_variable 和 std::condition_variable_any
  • <future>:通过特殊的provider进行数据的异步访问,实现线程间的通信,主要用于支持异步访问。
多线程示例
简单多线程

一个简单的多线程:

#include <iostream>
#include <thread>
using namespace std;
void thread_test()
{
   
    std::cout << "I'm thread_test()\n";
}
int main()
{
   
    std::thread t1(thread_test);
    cout << "I'm main_thread\n";
    //do somtthing
    t1.join();
    return 0;
}

部分需要补充的点:

  • main函数构建了一个std::thread对象t1,构造的时候传递了一个函数参数,这个参数就是线程的入口函数,函数执行完了,整个线程也就执行完了,线程创建成功后,就会立即启动
  • 一旦线程开始运行, 就需要显式的决定是要等待它完成(join),或者分离它让它自行运行(detach)。注意:只需要在std::thread对象被销毁之前做出这个决定
  • 调用join(),主线程会一直阻塞着,直到子线程完成,join()函数的另一个任务是回收该线程中使用的资源,如果采用detach的话表示子线程和主线程分离,这样子线程将有操作系统管理,主线程结束后也thread对象被析构,但是该线程仍将继续执行至结束。
detach和join的区别

在任何一个时间点上,线程是可结合的(joinable),或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死;在被其他线程回收之前,它的存储器资源是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。也就是说,分离状态还是可结合状态主要决定一个线程以怎样的方式终结。

当thread::join()函数被调用后,调用它的线程会被block,直到线程的执行被完成。基本上,这是一种可以用来知道一个线程已结束的机制。当thread::join()返回时,OS的执行的线程已经完成,C++线程对象可以被销毁。

当thread::detach()函数被调用后,执行的线程从线程对象中被分离,已不再被一个线程对象所表达–这是两个独立的事情。C++线程对象可以被销毁,同时OS执行的线程可以继续,也就是说主线程结束后该线程仍然可以继续运行,因此如果不关心一个线程的结束状态,那么也可以将一个线程设置为 detached 状态,从而让操作系统在该线程结束时来回收它所占的资源。

实际上,程序员应该在thread对象执行流程到析构函数前总是要么join,要么detach一个线程。当一个程序终止时(比如main返回),剩下的在后台的detached线程执行不会再等待;相反它们的执行会被挂起并且它们的本地线程对象会被销毁。通常情况下使用join即可。

否则会有问题:

#include <iostream>
#include <thread>  
#include <Windows.h>  
using namespace std;  
void test_thread()  
{
     
        cout << "Another thread  is working!\n" ;  
}    
int main()  
{
     
    thread task(test_thread);  
    cout << "Main thread is working!\n";  
    system("pause");  
}

这是一个很简单的多线程程序,但是并没有对task线程进行join或者detach,运行结果:

PS D:\vscode_c> ./test2
Main thread is working!
Another thread is working!
请按任意键继续. . .
terminate called without an active exception

出现这个情况的原因就是std::thread在main()结束的时候,被销毁了,解决办法就是对每一个进程都进行join或者detach(根据具体需求)。在代码上加入task.join(); 即可

join多线程

join函数会阻塞主流程,所以子线程都执行完成之后才继续执行主线程

#include <iostream>
#include <thread>  
#include <Windows.h>  
using namespace std;  
void thread1()  
{
     
    for (int i = 0; i < 5; i++)  
    {
     
        cout << "Thread 1 is working!\n" ;  
        Sleep(200);  
    }  
}  
void thread2()  
{
     
    for (int i = 0; i < 5; i++)  
    {
     
        cout << "Thread 2 is working!\n" ;  
        Sleep(100);  
    }  
}  
  
int main()  
{
     
    thread task01(thread1);  
    thread task02(thread2);
    task01.join();
    task02.join();
    for (int i = 0; i < 5; i++)  
    {
     
        cout << "Main thread is working!" << endl;  
        Sleep(200);  
    }
    system("pause");  
}

运行结果:

PS D:\vscode_c> ./test                
Thread 1 is working!
Thread 2 is working!
Thread 2 is working!
Thread 1 is working!
Thread 2 is working!
Thread 2 is working!
Thread 1 is working!
Thread 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值