c++中的并发线程(二)

本文详细介绍了C++中std::thread的detach()和join()方法,讨论了线程分离与等待线程完成的实践,强调了joinable()在判断线程状态中的作用,并提醒了在使用线程时应避免的异常问题,特别是涉及局部变量和资源生命周期的管理。此外,还展示了使用lambda表达式创建线程的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.线程分离–detach()

主线程不必等子线程运行完毕,先走为敬!

struct func
{
  int& i;
  func(int& i_) : i(i_) {}
  void operator() ()
  {
    for (unsigned j=0 ; j<1000000 ; ++j)
    {
      do_something(i);           // 1. 潜在访问隐患:悬空引用
    }
  }
};

void oops()
{
  int some_local_state=0;
  func my_func(some_local_state);
  std::thread my_thread(my_func);
  my_thread.detach();          // 2. 不等待线程结束
}

主函数线程已结束,my_thread线程中的函数还在运行.

2.等待线程完成–join()

  • 将my_thread.detach()替换为my_thread.join(),就可以确保局部变量在线程完成后,才被销毁.
  • 调用join()的行为,还清理了线程相关的存储部分,这样std::thread对象将不再与已经完成的线程有任何关联。这意味着,只能对一个线程使用一次join();一旦已经使用过join(),std::thread对象就不能再次加入了,当对其使用joinable()时,将返回false。

3.判断是否可以成功使用join()或者detach()的-joinable()

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

void myprint()
{
    cout<< "我的线程开始执行了"<<endl;
    cout<< "我的线程运行结束了"<<endl;
}
int main (void)
{
    thread mytob(myprint);
    if (mytob.joinable())
    {
        cout<<"true"<<endl;
    }
    else
    {
        cout<<"false"<<endl;
    }
    mytob.join();
    if (mytob.joinable())
    {
        cout<<"true"<<endl;
    }
    else
    {
        cout<<"false"<<endl;
    }
    cout<<"i love china "<<endl;
    return 0;
}

运行结果

true
我的线程开始执行了
我的线程运行结束了
false
i love china 

所以可以改进成这样的形式:

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

void myprint()
{
    cout<< "我的线程开始执行了"<<endl;
    cout<< "我的线程运行结束了"<<endl;
}
int main (void)
{
    thread mytob(myprint);
    if (mytob.joinable())
    {
        mytob.join();
    }

    return 0;
}

4.异常问题应避免的

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

class TA{
public:
    int &m_i;
    TA(int &i):m_i(i) {}
    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;
    }
};
int main (void)
{
    int mi=6;
    TA ta(mi);
    thread mytob(ta);
    mytob.detach();
    cout<<" i love china "<<endl;
    return 0;
}

运行结果为:

i love china 
m

原因这是因为主线程运行完之后,引用的变量就已经被销毁了.但这个变量还在子线程中在用,所以导致程序异常,产生不可预料的结果.
另一个知识点是:一旦调用了detach(),那主线程执行结束了,这里用到的ta对象还存在吗?答案是不存在的

但这个对象是被复制到子线程中去,原来的ta会被销毁,但是所复制的TA对象依旧存在.所以只要这个TA类对象里没有引用,没有指针,那么就不会产生问题.

5.用lambda表示

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


int main (void)
{
   auto mylamthread =[]{
    cout<<"我的线程开始了"<<endl;
    cout <<"我的线程结束了"<<endl;
   };
    thread mytob(mylamthread);
    mytob.join();
    cout<<"i love china "<<endl;
    return 0;
}

运行结果为:

我的线程开始了
我的线程结束了
i love china 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值