c++11并发与多线程(第二讲)

#include <iostream>
#include <thread>
#include <string>
using namespace std;
/*
int main()
{
    范例演示线程运行的开始和结束
    程序运行起来,生成一个进程,该进程所属的主线程开始自动运行;

    //实际上是主线程执行,主线程从mian函数开始执行,函数返回则线程执行结束。
    cout << "Hello world!" << endl;
    return 0;
}
*/


//自己创建一个线程,也需要从一个函数开始运行;
void my_print()
{
    cout << "我的线程 Hello my_print!" << endl;
    cout << "我的线程 Hello my_print!" << endl;
    cout << "我的线程 Hello my_print!" << endl;
    cout << "我的线程 Hello my_print!" << endl;
    cout << "我的线程 Hello my_print!" << endl;
    cout << "我的线程 Hello my_print!" << endl;

    cout << "我的线程 执行完成了。。。" << endl;
}

int main()
{
    /*
    主线程从main()开始执行,那么我们自己创建的线程,也需要从一个函数开始运行(初始函数),一旦函数运行完毕,就代表着我们这个线程运行结束。

    整个进程是否执行完毕的标志是:主线程是否执行完,如果主线程执行完毕了,就代表整个进程执行完毕了;
    此时,一般情况下:如果其他子线程还没有执行完毕,那么整个子线程也会被操作系统强行终止。
    所以一般情况下:结论,如果想保持子线程(自己用代码创建的线程)的运行状态,那么就需要让主线程一直保持运行,不要让它运行完毕
    这个规律有例外,老师后续会解释这种例外,大家目前先这样理解和记忆.
    a)包含一个头文件 #include <thread>
    b)初始函数要写。
    这是需要明确一点:有2个线程在跑,相当于整个程序的执行有两条线在同时走,所以可以同时干两件事。
    即使一条线被堵住了,也不影响另一条线的执行。
    (1.1)thread:是一个标准库里的类
     std::thread my_thread1(my_print);
    a)my_print是一个可调用对象
    b)创建了线程,线程执行的入口函数my_print
    c)my_print线程开始执行。

    (1.2)join():加入、汇合,说白了就是阻塞,柱塞主线程,让子线程执行完毕,然后子线程和主线程,
    让子线程和主线程汇合,然后主线程再往下走。
    my_thread1.join();主线程柱塞在这里等待my_print执行完,这个join()就执行完毕主线程就继续向下执行。

    如果主线程执行完毕了,但是子线程还没有执行完成,这种程序是不合格的,程序也是不稳定的。
    一个书写良好的程序,应该是主线程等待子线程执行完成后,自己才能退出。
    (1.3)detach():  分离,也就是主线程不和子线程汇合了,你主线程执行你的,我子线程执行我的,你主线程也不必等我子线程运行结束
    为什么引入detach()我们创建了很多子线程,让主线程逐个等待子线程结束,这种编程方法不好,所以引入了detach();
    其实最好的做法是让主线程等待每一个子线程执行结束。
    一旦detach后,与主线程子关联的thread对象,就会失去与这个主线程的关联。
    这时这个子线程就会驻留在后台运行,主线程与子线程失去联系
    子线程就会被c++运行时库接管了。当子线程执行完毕后,由运行时库负责清理这个线程相关的资源(守护线程)
    一旦调用了deatch(),就不能再使用join()了,否则系统报异常。
    (1.4)  joinable():判断是否可以join()或者detach()。
     如果返回true(表示可以join也可以detach)
     如果返回false表示不可以join和detach
    */
    std::thread my_thread1(my_print);
    cout <<my_thread1.joinable()<< endl;//1 true
    //my_thread1.join();
    my_thread1.detach();
    cout <<my_thread1.joinable()<< endl;//0 false
    cout << "Hello world!" << endl;
    return 0;
}


    二:其他创建线程的手法
    (2.1)用类,以及一个问题范例

#include <iostream>
#include <thread>
#include <string>
using namespace std;
class A
{
public:
    void operator()() //不能带参数
    {
        cout << "我的线程 operator执行了" << endl;
        cout << "我的线程 operator执行了" << endl;
        cout << "我的线程 operator执行了" << endl;
        cout << "我的线程 operator执行了" << endl;
    }
};
int main()
{
   
    A a1;
    std::thread my_thread2(a1);//使用类对象创建线程,线程函数是operator()
    cout <<my_thread2.joinable()<< endl;//true
    my_thread2.join();
    //my_thread1.detach();
    cout <<my_thread2.joinable()<< endl;//0 false
    cout << "Hello world!" << endl;
    return 0;
}

#include <iostream>
#include <thread>
#include <string>
using namespace std;

class A
{
public:
    int &m_i;
    A(int &i):m_i(i)
    {
        cout << "构造函数执行了" << endl;
    }
    A(const A &a1):m_i(a1.m_i)
    {
        cout << "拷贝构造函数执行" << endl;
    }
    ~A()
    {
        cout << "析构函数执行" << endl;
    }
    void operator()()//不能带参数
    {
        cout << "我的线程 operator执行了" << endl;
        cout << "m_i的值为:"<<m_i<< endl;
        //这边的m_i来着主线程,如果主线程结束了,回收了m_i的内存,那么就会出问题,打印的值无效
        cout << "m_i的值为:"<<m_i<< endl;
        cout << "m_i的值为:"<<m_i<< endl;
        cout << "m_i的值为:"<<m_i<< endl;
    }
};
int main()
{
    /*
    二:其他创建线程的手法
    (2.1)用类,以及一个问题范例

    */
    int my_i=6;

    A a1(my_i);
    std::thread my_thread2(a1);//使用a1可调用类对象
    /*一旦调用了detach(),如果主线程结束了,那么这边的a1对象还存在吗?
    实际上这个a1是被复制到线程中去了。所以执行完主线程后a1会被销毁。
    但是复制到子线程中的a1对象依然存在,所以,只要a1对象中没有引用和指针,那么就没有什么问题
    */
    //my_thread2.join();
    my_thread2.detach();
    cout <<my_thread2.joinable()<< endl;//0 false
    cout << "Hello world!" << endl;
    return 0;
}


使用  my_thread2.detach();的结果,从结果看出m_i<值出问题了

使用  my_thread2.join();的结果,

第一次调用的析构函数是复制进子线程的对象被析构了

第二次析构是主线程中的对象a1被析构

int main()
{
    /*
    二:其他创建线程的手法
 
    (2.2)使用lambda表达式
    */
    auto my_lambda_th = []
    {
        //自己创建一个线程,也需要从一个函数开始运行;
        cout << "我的线程 Hello my_lambda_thread!" << endl;
        cout << "我的线程 Hello my_lambda_thread!" << endl;
        cout << "我的线程 Hello my_lambda_thread!" << endl;
        cout << "我的线程 Hello my_lambda_thread!" << endl;
        cout << "我的线程 Hello my_lambda_thread!" << endl;
        cout << "我的线程 Hello my_lambda_thread!" << endl;
        cout << "我的线程 执行完成了。。。" << endl;
    }; 这边的分号不要丢了
    std::thread my_thread3(my_lambda_th);//lambda表达式
    my_thread3.join();
    //my_thread2.detach();
    cout << "Hello world!" << endl;
    return 0;
}

发布了101 篇原创文章 · 获赞 73 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/usstmiracle/article/details/104137971