zoukankan      html  css  js  c++  java
  • 并发、线程的基本概念&线程启动结束

    并发、进程、可执行程序、进程、线程的基本概念

    1.并发 
    并发当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。每次切换需要额外的开销(保存运行状态、还原现场)占用程序运行时间。线程的数量过多效率反而下降。
    2.并行
    当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行。
    3.可执行程序
    一个文件,windows下以.com或.exe为后缀,liunx,ls -la,rwxrwxrwx(x执行权限)
    4.进程
    计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。(可执行程序运行起来)
    5.线程
    又叫轻量进程,是程序执行流的最小单元。每一个进程有一个主线程,可以有多个线程。一个进程内的线程共享内存(全局变量、指针、引用可在线程间传递,开销小于多进程,但是会造成数据一致性的问题)。
    

    线程启动结束

    主线程从main()函数开始,自己创建的线程也需要从一个函数开始执行,这个函数执行完成,则线程消亡。
    如果主线程结束,进程结束,一般情况下该进程的所有线程结束。
    thread:标准库里的一个类

    join() (汇合)

    join:阻塞主线,让主线程等待子线程执行完毕
    用函数

    #include<iostream>
    #include<thread>
    using namespace std;
    void print()
    {
        cout<<"子线程开始"<<endl;
        cout<<"子线程结束"<<endl;
    }
    int main()
    {
        thread myThread(print);  //创建线程(入口为print())
        myThread.join();         //阻塞主线程 等待子线程执行完成
        cout<<"主线程结束"<<endl;
        return 0;
    }
    

    用类对象

    #include<iostream>
    #include<thread>
    using namespace std;
    class TA
    {
    public:
        void operator()()  //重载(),不能带参数
        {
            cout<<"子线程开始"<<endl;
            cout<<"子线程结束"<<endl;
        }
    
    };
    
    int main()
    {
        TA ta;
        thread myThread(ta);     //传入可调用对象
        myThread.join();         //阻塞主线程 等待子线程执行完成
        cout<<"主线程结束"<<endl;
        return 0;
    }
    

    用lambda表达式

    #include<iostream>
    #include<thread>
    using namespace std;
    
    int main()
    {
        auto my = []{
            cout<<"子线程"<<endl;
        };
        thread myThread(my);     //传入可调用对象
        myThread.join();
        return 0;
    }
    

    如果去掉myThread.join();可能会出现主线程执行完后子线程未执行完成。

    detach() (分离)

    detach:主线程和子线程分离,主线程可以先执行完成,不用和子线程汇合。
    detach后主线程关联和thread对象会与主线程失去关联,子线程会到后台运行。

    以下程序有一个坑点!!!

    在用detach()时,当主线程执行完成后,类中值引用的主线程局部对象val将会被回收,但是子线程依然要打印val的值,此时程序时错误的!(引用,指针局部对象)
    创建子线程中的局部的类对象是被复制到线程中去的,所以没有问题。

    #include<iostream>
    #include<thread>
    using namespace std;
    class TA
    {
    public:
        int &val;
        TA(int &val):val(val){}
        void operator()()  //重载(),不能带参数
        {
            cout<<val<<endl;
        }
    };
    
    int main()
    {
        int val=100;
        TA ta(val);
        thread myThread(ta);     //传入可调用对象
        myThread.detach();
        return 0;
    }
    

    joinable()

    判断是否能join()或detach()

  • 相关阅读:
    Interesting Finds: 2008.06.12
    8月19号
    8月22号
    8月20号
    8月21号
    第七章 Nginx配置虚拟主机
    第六章 Nginx配置文件详解
    第五章 Nginx搭建上传作业平台
    sqlserver2005提供的xml数据类型操作xml串
    事必躬亲利与弊
  • 原文地址:https://www.cnblogs.com/xcantaloupe/p/10372605.html
Copyright © 2011-2022 走看看