c++ 创建线程注意事项

  • 整个进程执行的完毕结束的标志是主线程结束;
  • 此时,如果其他子线程还没有执行完毕,那么子线程也会被操作系统强行终止,系统抛出异常
  • 良好的程序应该是主线程等待子线程执行完毕后,自己才能退出
  • 步骤:a)包含头文件
    b)自定义线程执行函数
    c)创建子线程thread mythread(mySonThread)
    d)join() :汇合,阻塞主线程并等待子线程执行完,继续往下执行主线程
  • detach():分离,主线程不与子线程汇合,各自独立自行,主线程结束,子线程也能够运行
    一旦detach()后,与这个线程关联的thread对象就会失去与这个主线程的关联,此时子线程就会驻留后台运行
    这个子线程将会被系统运行时库接管,当这个子线程执行完成后,由运行时库负责清理该线程相关的资源(守护线程)
    使用detach将会失去对线程的控制
  • join与detech不能同时使用
  • joinable():判断线程是否join或者detach成功,返回true成功,false失败
  • 如果线程传递int 这种简单的数类型,建议值传递,不要传引用
  • 如果传递类对象,避免隐士转换,要在创建线程这一步中,构建临时对象。在线程执行函数中,参数入口采用引用的形式,避免又多一次构造
#include <iostream>
#include <unistd.h>
#include <thread>
#include "stdio.h"
#include <string>
using namespace  std;

/**
 *  mySonThread 线程执行函数
 */
int mySonThread()
{
 cout <<"子线程:开始"<<endl;
    for(int i=0;i<10;i++) {
        cout <<"子线程执行第:"<<i<<" 次"<<endl;
    }
    cout <<"子线程结束"<<endl;
    return  0;
}

/**
 * 用类对象创建线程
 */
class SonTheardClass{
public:
    SonTheardClass(int i):num(i)
    {
        cout <<"构造函数被执行,线程ID:"<<this_thread::get_id()<<endl;
    }
    SonTheardClass(const SonTheardClass &mysonthread):num(mysonthread.num)
    {
        cout<<"拷贝构造被执行,线程ID:"<<this_thread::get_id()<<endl;
    }
    void operator() ()//不能带参数
    {
        cout<<"mySonTheardClass is begining!"<<endl;
        cout<<"作为类参数对象被执行,线程ID:"<<this_thread::get_id()<<endl;
        cout<<"mySonTheardClass is over!"<<endl;
    }
    ~SonTheardClass(){
        cout<<"析构被执行,线程ID"<<this_thread::get_id()<<endl;
    }
public:
    int num;
};
void mytempthread(const int &i,char *buff1,const string &buff2)
{
    cout<<"mytempthread is begining!"<<endl;

    cout<<"i= "<<i<<endl;
    const int *addr_i_thread=&i;
    cout<<"addr_i_thread= "<<addr_i_thread<<endl;//可以观察到addr_i_thread与addr_i所表示的地址不一样,因此可以断定,当线程中即使传入引用,其实并不是真实的引用,也是值传递,因为将i又额外的复制了一份存入到不同的地址中,当主线程结束,不会影响子线程

    printf("addr_buff1_thread= %lx\n",buff1);//可以观察到,当线程传入字符串指针时,addr_buff_thread与addr_buff一致,也就是说两个线程共用一个内存,如果主线程结束,那么子线程就会出现错误
    printf("addr_buff2_thread= %lx\n",&buff2);//可以观察到当传入string引用时,则addr_buff_thread与addr_buff不一致,也就是两个线程没有共用一个线程,因此使用线程在传字符串时,要使用string&

    cout<<"mytempthread is over!"<<endl;
}
int main(int argc, char *argv[])
{

    cout << "主线程:开始"<<endl;//主线程是从main函数开始执行,执行到return ,主线程结束
    SonTheardClass mySonTheardClass(6);

    thread thread1(mySonThread);//创建线程,线程起点是mySonThread
    //thread1.detach();
   thread1.join();//主线程执行到这里开始阻塞,等待mySonThread执行完,主线程继续往下执行

    thread thread2(mySonTheardClass);//类对象作为线程参数传递
    thread2.join();
    int i=2;
    const int *addr_i=&i;
    cout<<"addr_i= "<<addr_i<<endl;
    char buff[]="temp buff";
    cout<<"addr_buff= "<<&buff<<endl;
    //thread thread3(mytempthread,i,buff,buff);//注意第三个参数时什么时候转换成string的                                                                                                //事实上有可能主线程buff已经被回收了,子线程才用到这个buff,才开始转换。
    thread thread3(mytempthread,i,buff,string(buff));//传递临时对象做为线程参数,注意参数3,应该在此处进行转换。
    thread3.join();

    cout<<"主线程:结束"<<endl;

    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值