多线程入门-1

多线程入门学习


以下内容总结自KuangXiang老师免费分享在网易云课堂上的视频教程《C++11并发与多线程》,感谢KuangXiang老师的分享


1.基本概念

  1. 什么叫并发
      两个或者多个任务(独立任务)同时发生;
      单核CUP下是没有并发的,单核CPU下所谓的“并发”是由操作系统调度,每秒钟进行多次所谓的“任务切换”。这种任务切换称为上下文切换,上下文切换是有时间开销的,比如操作系统要保存切换时的各种状态信息、执行进度,待切换回来的时候要知道原来的状态。
  2. 什么叫进程
      在windows下运行起来的一个exe文件就是一个进程。 因为主线程是自动启动,所以一个进程至少有一个线程即主线程。
  3. 什么叫线程
      线程其实就是用来执行代码的。每个进程(即运行起来的可执行程序),都有一个主线程,这个主线程在当前进程中是唯一的,也就是一个进程中只能有一个主线程。当你执行可执行程序时会自动创建一个主线程。进程结束,主线程也就结束了
      运行程序时,实际上是进程的主线程来执行(调用)这个main函数中的代码。除了主线程外,也可以通过自己写代码创建其他线程,如果把线程理解成一个代码的执行通路或道路的话,自己创建的线程走的是别的道路。每创建一个新线程,就可以在同一个时刻,多干一个不同的事情(多走一条不同的代码执行路径)
    线程不是越多越好,每个线程都需要一个独立的堆栈空间(1M大小),太多的线程占用内存,而且线程之间切换也是有时间消耗,线程太多,把时间都花费在线程切换上了,占用原本属于程序运行的时间。创建的线程最大数目不建议超过200-300个,有的时候线程太多反而会降低效率。
    • 主线程
      主线程从main()开始执行,自己创建的线程,也需要从一个函数开始运行(初始函数),一旦这个函数运行完毕,就代表这个线程运行结束。比如main函数运行结束,主线程就结束,而主线程结束代表整个进程执行完毕了,如果主线程结束了还有其他子线程在运行,那其他子线程也会被强制终止。如果想保持子线程的运行状态的话,不要让主线程结束(这句话也有例外)
//主线程开始执行如下main()函数
main(){
   //..各种代码
return ;
//主线程执行完main中return后,表示整个进程运行完毕,此时主线程结束运行,这个进程也结束运行。
  1. 如何实现并发
    手段:1.通过多个进程实现并发;2.在单独的进程中,通过创建多个线程来实现并发,自己写代码创建除了主线程外的其他线程。
  2. 多进程并发
    word启动后是进程,excel启动后也是一个进程 同时启动两个程序就是多进程并发。
    进程之间的通信:(1)同一台电脑:管道,文件,消息队列,共享内存;(2)不同电脑上:socket通信技术;
  3. 多线程并发 (单个进程中创建多个线程)
    每个线程都有自己独立的运行路径,但是一个进程中的所有线程共享内存空间(如全局变量,指针,引用 都可以在线程之间传递)。共享内存带来新的问题:数据一致性问题,比如多个线程对某块内存数据的操作。平时使用多线程多于多进程
    • 和进程相比,线程有如下优点:
      (1)线程启动速度更快,更轻量级;(2)系统资源开销更小,执行速度更快,比如共享内存这种通信方式比任何其他的通信方式都快;
    • 缺点:
      (1)多线程使用起来有一定难度,要小心处理数据的一致性问题。

2. 写多线程程序

  1. 基本操作

    • 需要包含include<thread>头文件,来使用thread

    • 自己创建的线程也需要从一个函数开始运行(初始函数);

    • main()函数中写代码

    //p-1
    //以下代码就有两个线程在跑,一个是主线程,一个是自己创建的线程,这里两个线程是同时进行,区别与函数调用
    #include<iostream>
    #include<thread>
    using namespace std;
    void myprint()
    {
       cout<<"my thread~1"<<endl;
       cout<<"my thread~2"<<endl;
       cout<<"my thread~3"<<endl;
       cout<<"my thread~4"<<endl;
    }
    int main()
    {
       thread myt(myprint);//1.创建了线程,指定了线程执行入口是myprint()。2.该语句创建后,myprint函数就开始执行了
       myt.join();//在这一步,join函数会阻塞主线程往下执行,让主线程停在这里等待子线程执行到这一步后,主线程往下执行下面的步骤,
      //myt.detach();//detach分离主线程和子线程,主线程不用等待子线程,两者可以分开跑,但是在主线程结束时,即到达`return 0` 时,子线程即使没有结束也会终止。
    
       cout<<"In Main function"<<endl;
       return 0;
    }
    
  2. thread
    thread类是标准库中的一个类,目的是用来创建线程的,p-1例子中myt就是创建的一个thread的对象。myt(myprint)创建对象,并且用myprint()函数初始化myt对象。一旦初始化该对象后,myprint()函数就开始执行,也就是该线程就开始执行了。
    2.1. join()函数
    阻塞主线程,让主线程停在调用join()处,让主线程等待子线程执行到join函数处,主线程再开始接着执行。有些时候不使用join函数会出现主线程已经执行完,而子线程还没有执行完,程序出现异常终止。
    2.2. detach()函数 (使用的较少)
    传统多线程程序,主线程要等待子线程执行完毕,然后自己再退出 。 ** 一旦调用了detach()函数,就不能在使用join函数,让主线程等待子线程了**
    使用detach()函数,主线程不用和子线程汇合了,主线程执行主线程的,子线程执行子线程的,主线程运行结束子线程依然可以接着执行自己的剩余部分。 但要注意主线程结束时,子线程如果没有执行完也会被迫结束。

    • 引入detach的原因:
      如果创建了很多子线程,让主线程逐个等待子线程结束,这样的编程方法不太好。

    2.3. joinable()
    判断是否可以当前对象(比如myt)是否可以使用join()或者detach()函数。如果可以使用,joinable的返回值为true,即可以使用join或detach函数。

  3. 创建线程的方法
    创建线程,需要将可调用对象作为参数传递给thread类对象。
    3.1. 函数名作为可调用对象创建线程
    比如例子p-1就是将函数名作为可调用对象传递给myt对象来创建了一个线程。
    3.2. 类对象作为可调用对象创建线程
    使用类对象时,要注意处理引用

     //p-2
     #include<iostream>
     #include<thread>
     using namespace std;
     class TA
     {
     public:
     void operator()()//需要重载"()"类对象才能作为可调用对象
     {
        cout<<"我的线程operator()开始执行了"<<endl;  
         cout<<"我的线程operator()开始执行了"<<endl;   
     }
     };
     int main()
     {
        TA ta;
        thread myt(ta);//ta:可调用对象。
        myt.join();
        //myt.detach()
        cout<<"this in In Main function"<<endl;
        return 0;
     }
    

    3.3. 用lamda表达式创建多线程

    //p-3
     #include<iostream>
     #include<thread>
     using namespace std;
     int main()
     {
        auto mylamthread=[]{
        cout<<"我的线程lamda开始执行"<<endl;
        //...
        cout<<"我的线程lamda执行结束"<<endl;
        };
        thread myt(mylamthread);
        myt.join();
        //myt.detach();
        cout<< "this in In Main function1" << endl;   
        cout << "this in In Main function2" << endl;   
        cout << "this in In Main function3" << endl;   
        return 0;   
     }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值