当前位置: 首页 > wzjs >正文

网站文章后台写完前台不显示天津seo外包团队

网站文章后台写完前台不显示,天津seo外包团队,做公益网站需要什么资质,网站后台制作教程0.前言本篇主要围绕C线程知识展开,本篇并不会一次性写完,而是会不断填充,以便后续回看。1.线程基础概念线程与进程的区别:线程是进程的执行单元,共享进程资源(内存、文件描述符等),切…

0.前言

本篇主要围绕C++线程知识展开,本篇并不会一次性写完,而是会不断填充,以便后续回看。

1.线程基础概念

  • 线程与进程的区别:线程是进程的执行单元,共享进程资源(内存、文件描述符等),切换开销更小。
  • 并发与并行的区别:并发是任务交替执行,并行是任务同时执行(依赖多核CPU)。
  • C++标准库支持:<thread>头文件提供线程管理接口。

2.C++线程常用接口

2.1创建线程

通过std::thread构造函数,传入可调用对象(函数、Lambda、成员函数等)。从下面可以看到常用的线程创建方式。

#include<iostream>
#include<thread>
using namespace std;void test(){cout<<"test"<<endl;
}void test1(int i){cout<<"test(int i)"<<i<<endl;
}void test2(int& i){i++;cout<<"test(int i)"<<i<<endl;
}class ThreadDemo{public:void test(int i){cout<<"ThreadDemo::test(int i)"<<i<<endl;}
};int main(void){int i = 1;// 情形1:全局函数创建线程thread th1(test);thread th2(test1,i);// 情形2:成员函数创建线程ThreadDemo td;thread th3(&ThreadDemo::test,&td,i);// 引用传参thread th4(test2,std::ref(i));this_thread::sleep_for(1000ms);// 情形3:lambda创建线程thread th5([&i](){i = i+1;cout<<"lambda"<<i<<endl;});th1.join();th2.join();th3.join();th4.join();th5.join();cout<<i<<endl;return 0;
}

这里需要着重注意的是,如果采用引用(或指针)传参,一定要保证线程在执行完毕前,其参数不能被销毁。

 2.2线程回收

常见的线程回收包括:join()等待线程结束,detach()分离线程(后台运行)。

2.3线程参数

前文提到过,如果采用拷贝给线程传递参数安全性较高,但是如果传递引用参数的话,必须注意参数在线程使用过程中不能被释放。

比如有如下代码:

struct threaddemo
{int& i;threaddemo(int& i_) : i(i_) {cout<<&i<<endl;}void test(int i){cout<<i<<endl;}void operator() (){for (unsigned j=0 ; j<10 ; ++j){test(i);           // 访问局部变量引用}}
};int main(void){{int l_val=0;threaddemo tm(l_val);thread my_thread(tm);my_thread.detach();          // 2. 不等待线程结束}return 0;
}

如果实例化上述类中的对象并创建线程(main中),则会间接引用到局部变量,会出现安全问题。

2.4线程管理

每次创建一个线程都需要找个时机调用join(),这确实有点反人类了。常见的方法是采用RAII的方法。完整的代码大概是这样的:

#include<thread>
#include<iostream>
using namespace std;struct threaddemo
{int& i;threaddemo(int& i_) : i(i_) {cout<<&i<<endl;}void test(int i){cout<<i<<endl;}void operator() (){for (unsigned j=0 ; j<10 ; ++j){test(i);           // 1. 潜在访问隐患:悬空引用}}
};class RAIIthread{
public:thread& th;RAIIthread(thread& th_) : th(th_) {}~RAIIthread(){if(th.joinable())cout<<"exec"<<endl;th.join();}
};int main(void){{int l_val=0;cout<<&l_val<<endl;threaddemo tm(l_val);thread my_thread(tm);RAIIthread raii_thread(my_thread);// my_thread.join();          // 2. 不等待线程结束}return 0;
}

这样每次线程执行完毕后,就可以自动调用join了。

3.共享数据保护

当多个线程同时操作共享数据(或代码段)时,可能存在竞争问题。为此,C++采用了锁机制解决这个问题。

3.1mutex基本使用

这里直接给个简单的例子:在多线程场景下向一个数组中添加元素。代码实现如下:

#include<iostream>
#include<vector>
#include<thread>
#include<mutex>using namespace std;// 向容器添加数据的任务
mutex m;
void addTask(vector<int>& vec,int i){m.lock();for(int j = 0;j<i;j++){vec.push_back(j);}m.unlock();
}// 打印容器元素
void printVec(const vector<int>& vec){for(auto i:vec){cout<<i<<" ";}cout<<endl;
}
// 
int main(void){vector<int> data;vector<thread> ths;for(int i = 0;i<5;i++){ths.push_back(thread(addTask,std::ref(data),1000));}// 回收线程for(auto &th:ths){th.join();}printVec(data);return 0;
}

在主函数中创建了五个线程,每个线程都会向vector添加1000个元素。因为加了mutex的原因,程序输出的vector大小是5000个。但是不加锁则一定几率出现小于5000个元素,甚至会报错。

3.2RAII+mutex

从3.1程序中可以看到,锁的释放需要特定的时机。C++标准库提供了std::lock_guard模板类,它能在创建时自动加锁,并在析构时自动解锁,即RAII。

那任务函数可以简化为:

void addTask(vector<int>& vec,int i){lock_guard<mutex> lg(m);for(int j = 0;j<i;j++){vec.push_back(j);}
}

补充

后续内容慢慢补充!

http://www.dtcms.com/wzjs/55745.html

相关文章:

  • 怎么引流到微信呢seo网络推广专员招聘
  • 天元建设集团有限公司电话号码seo新人培训班
  • 大型建站公司做网络推广的团队
  • 网站开发android客户端天津网站制作系统
  • 做食品网站需要什么条件天天seo站长工具
  • 网站开发阶段企业培训课程安排表
  • 县政府网站建设方案徐州seo外包公司
  • 网站维护项目免费的外链平台
  • 深圳购物商城网站建设网络销售公司怎么运作
  • 网站制作代码竞价网站
  • 企业的网站建设费账务处理广州:推动优化防控措施落
  • 微商平台appseo的中文是什么
  • 能免费做封面的网站指数运算公式大全
  • 网站图片自动轮换怎么做的山西优化公司
  • 网站链接分析seo快速整站上排名教程
  • 勒流网站建设百度搜索一下百度
  • 大连专业手机自适应网站制作登封网络推广公司
  • 广告公司有什么业务seo关键词排名优化系统源码
  • 建造师信息查询网郑州seo优化
  • discuz做资讯网站合适吗百度导航官网
  • 青岛企业如何建网站一个新手怎么去运营淘宝店铺
  • 怎样做外贸网站软件开发工资一般多少
  • 潍坊seo招聘聊城seo整站优化报价
  • 网站设置在哪里找百度指数电脑端查询
  • 网站公安备案2021关键词搜索排行
  • 网站建设的市场定位分析百度云登陆首页
  • 做百度手机网站排名seo诊断工具有哪些
  • javeweb网站建设站长之家ip地址查询
  • 哪个网站做网站方便关键词优化的建议
  • WordPress导出静态网页2019网站seo