并发编程2——线程启动、结束,创建线程多法、join,detach

目录
  • 自己用代码创建的其他线程
  • 需要从一个函数开始运行
  • 当这个函数运行完毕的时候
  • 代表这个线程运行结束

什么是多线程

不是一条线执行,而是多条线,可以同时干多个事,即使一条线被堵住了,另一条也可以顺利执行


多线程

主线程应该做的是等待子线程执行完毕后,自己才能最终退出

如果想让子线程不被OS强行终止

需要让主线程一直保持运行,不要让主线程运行完毕即可

thread类和join()函数

  • thread类是用来构建子线程对象
  • join()函数是用来阻塞主线程,让主线程等待子线程执行完毕的函数

主线程阻塞到join()这里等待go()执行完,当子线程执行完毕(然后子线程和主线程汇合),这个join()就会执行完毕,主线程就可以继续向下执行。

如果没有join()函数

  • 没有join()函数

    就会发生异常


    异常

如果有join()函数

  • 有join()函数

就可以顺利执行


顺利执行

detach()的使用

detach()是可以让主线程和子线程分离

  • 当调用了detach()之后,与主线程关联的thread对象就会失去与这个主线程的关联
  • 此时这个子线程会驻留在后台运行(主线程和这个子线程失去联系)

如果主线程提前退出了,子线程就会被C++运行时库接管,当子线程执行完的时候,运行时库会清理这个子线程的相关资源

这个线程一般被称为守护进程

detach()使用结果

detach()导致输出的格式是乱的,随机的,detach()后线程是不受控制的

detach()使用结果

什么是joinable()

如果一直没有调用过join()和detach(),那么joinable()就是true
如果调用过,那么joinable()就是false

因为join()和detach()不能同时调用,并且只能调用一次


其他创建线程的手法

之前的创建手法回顾

thread myobj(go)

这个go()是一个函数,也是一个可调用对象

(或者说是类对象)也可以作为一个可调用对象

如果使用detach()

可以看到析构函数只调用了一个,这个析构函数是析构主线程的那个可调用对象的,因为子线程那个还没执行完(蓝色箭头

使用detach()

如果使用join()

第一个析构函数是子线程的
第二个析构函数是主线程的

使用join()

“复制”还是“引用 or 指针”

如果我们用的是join(),那么用引用还是值传递都可以
如果用的是detach(),当主线程退出的时候,myi变量会被系统自动销毁,那么这个时候子线程中就没有东西可以执行了,就会有异常

需要注意的是这里的可调用对象ta进入子线程后是直接复制了一份,所以拷贝构造函数被执行了。

  • 所以说还是用join稳啊。

lambda表达式

  • 使用join()


    join()
  • 使用detach()


    detach()

小结

可以用函数、类对象、lambda表达式创建线程,作为线程的入口


博客示例代码

  • thread和join()
#include 
#include 

using namespace std;

void go()
{
    cout << "子线程开始执行了!" << endl;
    cout << "子线程运行完毕了!" << endl;
}

int main()
{
    thread myObj(go);

    myObj.join();
    cout << "主线程开始执行了!" << endl;

    return 0;
}
  • detach()
#include 
#include 

using namespace std;

void go()
{
    cout << "子线程开始执行了!" << endl;

    cout << "子线程运行完毕了1" << endl;
    cout << "子线程运行完毕了2" << endl;
    cout << "子线程运行完毕了3" << endl;
    cout << "子线程运行完毕了4" << endl;
    cout << "子线程运行完毕了5" << endl;
    cout << "子线程运行完毕了6" << endl;
    cout << "子线程运行完毕了7" << endl;
    cout << "子线程运行完毕了8" << endl;
    cout << "子线程运行完毕了9" << endl;
    cout << "子线程运行完毕了10" << endl;
}

int main()
{
    thread myObj(go);

    // myObj.join();
    myObj.detach();
    cout << "fucking bitch 1" << endl;
    cout << "fucking bitch 2" << endl;
    cout << "fucking bitch 3" << endl;
    cout << "fucking bitch 4" << endl;
    cout << "fucking bitch 5" << endl;
    cout << "fucking bitch 6" << endl;
    cout << "fucking bitch 7" << endl;
    cout << "fucking bitch 8" << endl;
    cout << "fucking bitch 9" << endl;
    cout << "fucking bitch 10" << endl;

    return 0;
}
  • 类对象
#include 
#include 

using namespace std;

class TA
{
public:
    int m_i;

    TA(int i) : m_i(i) { cout << "TA()构造函数被执行" << endl; }
    TA(const TA& ta) : m_i(ta.m_i) { cout << "TA()拷贝构造函数被执行" << endl; }
    ~TA() { cout << "~TA()析构函数被执行" << endl; }

    void operator() ()
    {
        cout << "m_i1的值为:" << m_i << endl;
        cout << "m_i2的值为:" << m_i << endl;
        cout << "m_i3的值为:" << m_i << endl;
        cout << "m_i4的值为:" << m_i << endl;
        cout << "m_i5的值为:" << m_i << endl;
        cout << "m_i6的值为:" << m_i << endl;
        cout << "m_i7的值为:" << m_i << endl;
        cout << "m_i8的值为:" << m_i << endl;
    }
};

int main()
{
    int myi = 6;
    TA ta(myi);
    
    thread myObj(ta);

    myObj.join();
    //myObj.detach();

    cout << "fucking bitch 1" << endl;
    cout << "fucking bitch 2" << endl;
    cout << "fucking bitch 3" << endl;
    cout << "fucking bitch 4" << endl;
    cout << "fucking bitch 5" << endl;
    cout << "fucking bitch 6" << endl;
    cout << "fucking bitch 7" << endl;
    cout << "fucking bitch 8" << endl;
    cout << "fucking bitch 9" << endl;
    cout << "fucking bitch 10" << endl;

    return 0;
}
  • lambda表达式
#include 
#include 

using namespace std;


int main()
{
    auto mylambdathread = []
    {
        cout << "我的线程开始执行了" << endl;

        cout << "我的线程执行结束了" << endl;
        cout << "我的线程执行结束了" << endl;
        cout << "我的线程执行结束了" << endl;
        cout << "我的线程执行结束了" << endl;
    };

    thread myobj(mylambdathread);
    // myobj.join();
    myobj.detach();

    cout << "Fucking bitch" << endl;

    return 0;
}

你可能感兴趣的:(并发编程2——线程启动、结束,创建线程多法、join,detach)