C++多线程编程(一)

文章目录[x]
  1. 1:C++多线程
  2. 1.1:第一个多线程
  3. 1.2:多线程共享数据

C++多线程

第一个多线程

多线程的缺点

  • 死锁

  • 乱序

  • 并发访问数据造成问题

  • 低效率

创建一个多线程程序

#include <iostream>
#include <thread>

//创建一个子线程函数
void hello()
{
    std::cout<<"heelo wold"<<std::endl;
}
int main()
{
    std::thread t(hello);   //开启一个线程
    std::cout<<"hello"<<std::endl;

    t.join();   //线程结束
    return 0;
}

查看该设备使用多少线程效率最高

#include <iostream>
#include <thread>

using namespace std;
void hello()
{
}
int main()
{
    unsigned int n=thread::hardware_concurrency(); //跑多少个线程时候效果最高
    cout <<n<<endl;
    return 0;
}

仅仅作为参考

detach()

传统多线程程序中,主线程要等待子线程执行完毕,然后自己才能向下执行

detach:分离,主线程不再与子线程汇合,不再等待子线程detach后,子线程和主线程失去关联,驻留在后台,由C++运行时库接管t.detach(),称为守护进程

detach子线程传递参数注意事项

原因:主线程退出释放资源,但子线程还没有进行获取资源

若用int等简单类型传递参数,建议使用值传递,不要用引用和指针类型

如果传递类对象,避免隐式转换,在创建线程时就构建临时对象,函数参数使用引用进行接收,如果不用引用的话,将会构造三次临时对象

测试代码

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

class A {
public:
  mutable int m_i; //m_i即使实在const中也可以被修改
  A(int i) :m_i(i) {}
};

void myPrint(const A& pmybuf)
{
  pmybuf.m_i = 199;
  cout << "子线程myPrint的参数地址是" << &pmybuf << "thread = " << std::this_thread::get_id() << endl;
}

int main()
{
  A myObj(10);
  //myPrint(const A& pmybuf)中引用不能去掉,如果去掉会多创建一个对象
  //const也不能去掉,去掉会出错
  //即使是传递的const引用,但在子线程中还是会调用拷贝构造函数构造一个新的对象,
  //所以在子线程中修改m_i的值不会影响到主线程
  //如果希望子线程中修改m_i的值影响到主线程,可以用thread myThread(myPrint, std::ref(myObj));
  //这样const就是真的引用了,myPrint定义中的const就可以去掉了,类A定义中的mutable也可以去掉了
  thread myThread(myPrint, myObj);
  myThread.join();
  //myThread.detach();

  cout << "Hello World!" << endl;
}

其他创建线程方法

1.类方法

class Ta
{
public:
  void operator()() //不能带参数
  {
    cout << "我的线程开始运行" << endl;
    //-------------
    //-------------
    cout << "我的线程运行完毕" << endl;
  }
};

int main(){
  Ta ta;
  thread myThread(ta);
  myThread.join();
  return 0;
}

2.匿名函数

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

  thread myThread(lambdaThread);
  myThread.join();
  return 0;
}

多线程共享数据

互斥量

lock(),unlock()

使用样例:

std::mutex my_lock;
void test(){
......
my_lock.lock();
/........
共享数据部分
...../
my_lock.unlock();
}

为了避免忘记使用lockunlock,可以使用std::lock_guard<std::mutex>进行智能管理释放

使用样例:

std::mutex my_lock;
void test(){
  ......
   std::lock_guard<std::mutex> tmp(my_lock)//tmp变量名
  /........
  共享数据部分
  ...../
}

std::lock(参数一,参数二。。。)

可以一次锁住多个互斥量

std::unique_lock<std::mutex>

用法:

当本线程所需的互斥量正被另一个线程所使用,并且需要较长时间才能获取到时候,本线程就会一直处于等待状态浪费资源,使用

std::unique_lock<std::mutex>的话可以在为拿到所时候进去处理其他任务

示例:

std::unique_lock<std::mutex> tmp(my_lock,std::try_to_lock);
if(tmp.owns_lock()){
//拿到了锁,进行处理
}
else{
//未拿到锁处理代码
}
点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像