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

福州网站建设要找嘉艺网络东营网签查询系统官方网站

福州网站建设要找嘉艺网络,东营网签查询系统官方网站,dedecms5.7装饰网站模板,做外贸有哪些好的网站目录 ​编辑 POSIX线程库 多线程创建 独立栈结构 获取线程ID pthread_self 线程终止 return终止线程 pthread_exit pthread_cancel 线程等待 退出码问题 线程分离 测试 线程ID及地址空间布局 ​编辑 POSIX线程库 pthread线程库是 POSIX线程库的一部分#xf… 目录 ​编辑 POSIX线程库 多线程创建 独立栈结构  获取线程ID  pthread_self  线程终止 return终止线程 pthread_exit pthread_cancel 线程等待 退出码问题 线程分离 测试  线程ID及地址空间布局  ​编辑 POSIX线程库 pthread线程库是 POSIX线程库的一部分POSIX线程库也叫原生线程库;         遵守 POSIX标准与线程有关的函数构成了一个完整的系列绝大多数函数的名字都是以“pthread_”开头的要使用这些函数库要通过引入头文pthread.h链接这些线程函数库时要使用编译器命令的 “-lpthread” 选项; 成功返回0失败返回-1 多线程创建 主线程创建一批线程; 没有在循环创建中添加sleep(); void* handler(void* arg) {const char* name (const char*)arg;while(true){coutnew thread sucess name:nameendl;sleep(1);} }int main() {pthread_t tid;char namebuff[64];for(int i 0;i5;i) {//格式化snprintf(namebuff,sizeof(namebuff),%s%d,thread:,i1);pthread_create(tid,nullptr,handler,namebuff); //}while(true){cout new thread create success, I am main thread endl;sleep(1);}return 0; } 观察发现线程编号不是我们预期的从1.2.3..开始的而是到了最后一个线程名字 而且线程确实创建出来了 添加循环创建时sleep()函数 ;将数组地址改为拷贝 //把参数封成结构体 class ThreadData { public:pthread_t tid;char namebuffer[64]; };void* start_routine(void* args) {ThreadData* td static_castThreadData*(args);//static_cast 安全的进行强制类型转换C11int cnt 10;while(cnt){cout cnt: cnt-- cnt: cnt endl;sleep(1);}delete td;return nullptr; }int main() { #define NUM 10//创建一批线程for(int i 0; i NUM; i){ThreadData* td new ThreadData();//每次循环new的都是一个新对象snprintf(td-namebuffer, sizeof(td-namebuffer), %s:%d, thread, i1);//i1 使线程下标从1开始pthread_create(td-tid, nullptr, start_routine, td);}//主线程while(1){cout new thread create success, name:main thread endl;sleep(1);}return 0; }主线程创建新线程太快了新线程都没有机会运行主线程就把10个新线程创建完毕了而传参namebuffer传过去的是 缓冲区namebuffer的起始地址第十个线程创建完成之后缓冲区的内容都被第十个线程的编号内容覆盖了所以第一次现象线程的编号都是 10 独立栈结构  线程栈主要用于存储线程的局部变量、函数参数以及调用堆栈。当一个线程开始执行时它的栈空间会被初始化并且随着线程的执行栈空间会被动态地扩展或收缩。 //把参数封成结构体 class ThreadData { public:pthread_t tid;char namebuffer[64]; };void* start_routine(void* args) {ThreadData* td static_castThreadData*(args);//static_cast 安全的进行强制类型转换C11int cnt 10;while(cnt){cout cnt: cnt-- cnt: cnt endl;sleep(1);}delete td;return nullptr; }int main() { #define NUM 10//创建一批线程for(int i 0; i NUM; i){ThreadData* td new ThreadData();//每次循环new的都是一个新对象snprintf(td-namebuffer, sizeof(td-namebuffer), %s:%d, thread, i1);//i1 使线程下标从1开始pthread_create(td-tid, nullptr, start_routine, td);}//主线程while(1){cout new thread create success, name:main thread endl;sleep(1);}return 0; } 在函数内部定义的变量叫局部变量具有临时性在多线程的情况下依旧适用因为每个线程都有自己的独立栈结构  获取线程ID  常见获取线程ID的方式有两种 创建线程时通过输出型参数获得通过调用pthread_self函数获得 pthread_self  void* start_routine(void* args) {//安全转换std::string name static_castconst char*(args);while(true){std::coutname running ...,ID: pthread_self()std::endl;sleep(1);} }int main() {pthread_t thread_id;//创建一个线程pthread_create(thread_id,nullptr,start_routine,(void*)thread 1:);//打印一下主线程的IDwhile(true){std::coutmain thread ID: pthread_self()std::endl;sleep(1);}// 等待子线程结束pthread_join(thread_id, NULL);return 0; }线程终止 如果需要只终止某个线程而不终止整个进程 可以有三种方法: 从线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit整个进程退出线程可以调用 pthread_ exit 终止自己一个线程可以调用 pthread_ cancel 终止同一进程中的另一个线程 return终止线程 在多线程程序中return关键字的使用有所不同 当非主线程时仅表示该线程将终止其执行在main函数中使用return则意味着整个进程将退出这会导致进程的所有资源被释放。 用例 主线程创建多个新线程后休眠2秒然后进行return那么整个进程也就退出了   class ThreadData { public:pthread_t tid;char namebuffer[64]; };void* start_routine(void* args) {ThreadData* td static_castThreadData*(args);//static_cast 安全的进行强制类型转换C11int cnt 10;while(cnt){cout new thread create success, name: td-namebuffer cnt: cnt-- endl;sleep(1);}delete td;return nullptr; }int main() { #define NUM 3//创建一批线程for(int i 0; i NUM; i){ThreadData* td new ThreadData();snprintf(td-namebuffer, sizeof(td-namebuffer), %s:%d, thread, i1);//i1 使线程下标从1开始pthread_create(td-tid, nullptr, start_routine, td);}//主线程cout new thread create success, name:main thread endl;sleep(2);//主线程两秒后退出return 0; } 如果非主线程执行到return仅代表该线程结束线程退出  pthread_exit 函数终止线程  exit 是用来终止进程的任何一个执行流调用 exit都会使整个进程退出pthread_exit函数的功能就是终止线程 注意 当pthread_exit()和return时如果返回值是一个指针该指针指向的内存空间应该是全局的或者malloc分配的(new 本质也是malloc)防止后面有其它线程通过该指针访问出错         当然为了避免潜在威胁最好确保返回的指针是指向全局malloc开辟的。这样可以确保即使线程退出其他线程仍然可以安全地访问这些内存。不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了 pthread_cancel 函数取消线程  // 定义一个用于存储线程数据的类 class ThreadData { public:int number; // 线程编号pthread_t tid; // 线程IDchar namebuffer[64]; // 缓冲区用于存储线程名称 };// 线程函数 void* start_routine(void* args) {ThreadData* td static_castThreadData*(args);int cnt 10;while (cnt 0){cout td-namebuffer cnt: cnt-- endl;sleep(1);}// 使用 pthread_exit 返回线程编号pthread_exit((void*)td-number); }int main() {vectorThreadData* threads; // 用于存储线程数据的向量 #define NUM 5 // 定义要创建的线程数量for (int i 0; i NUM; i) // 创建一批线程{ThreadData* td new ThreadData(); // 创建 ThreadData 实例td-number i 1; // 设置线程编号snprintf(td-namebuffer, sizeof(td-namebuffer), %s:%d, thread, td-number);pthread_create(td-tid, nullptr, start_routine, td);threads.push_back(td); // 把每个线程的信息 push 到 threads 向量中}// 主线程for (auto iter : threads){// 输出创建成功的线程信息cout create thread: iter-namebuffer : iter-tid success endl;}sleep(5); // 主线程休眠5秒// 取消线程for (auto iter : threads){// 取消线程pthread_cancel(iter-tid);cout pthread_cancel: iter-namebuffer endl;}// 等待线程结束for (auto iter : threads){void* ret nullptr;int n pthread_join(iter-tid, ret); // 等待线程结束并获取线程返回值// 断言assert(n 0);// 输出线程结束的信息和线程退出时返回的值cout join: iter-namebuffer success, thread_exit_code: (long long)ret endl;delete iter; // 释放 ThreadData 实例}// 主线程退出cout main thread quit endl;return 0; }一个线程被取消它的退出码是 -1 线程等待 线程跟进程一样创建后也需要主线程等待回收如果主线程不对新线程进行等待如果主线程不对新创建的线程进行等待那么这个新线程的资源将不会被及时回收。这会导致类似“僵尸进程”的问题也就是内存泄漏 已经退出的线程其空间没有被释放仍然在进程的地址空间内。创建新的线程不会复用刚才退出线程的地址空间 退出码问题 void* retval 和 void** retval 有什么关系线程函数start_routine函数的返回值类型也是 void* start_routine函数的返回值返回到哪里我们怎么获取线程的退出码即线程的返回值 pthread_join函数的参数 void** retval 是一个输出型参数用来获取线程函数结束时返回的退出结果 void** retval 是用来获取线程函数返回的退出结果因为线程函数的返回值是 void*所以需要用 void** 来接受 void*注意线程函数返回的退出结果是返回在线程库当中参数 void** retval 需要去线程库里面接受才可以返回 线程分离 新创建的线程是 joinable可以被等待的。这意味着线程退出后需要对其执行 pthread_join 操作来释放资源否则这些资源将不会被释放从而可能导致系统资源泄漏。如果不关心线程的返回值的话线程等待pthread_join是一种负担 可以使用 pthread_detach来分离线程。分离后的线程会在退出时自动释放其资源无需主线程进行 pthread_join操作。 测试  // 将线程ID转换为字符串 string changeID(const pthread_t thread_id) {char tid[128];// 将线程ID格式化为十六进制字符串snprintf(tid, sizeof(tid), 0x%x, thread_id);return tid; }// 线程函数 void* start_routine(void* args) {string threadname static_castconst char*(args);int cnt 5;while (cnt 0){// 输出线程名称和线程ID cout threadname running..., threadID: changeID(pthread_self()) endl;sleep(1);cnt--;}// 线程函数结束return nullptr; }int main() {pthread_t tid;// 创建一个新线程pthread_create(tid, nullptr, start_routine, (void*)thread 1);// 分离线程pthread_detach(tid); // 分离线程后线程将在退出时自动释放资源// 线程默认是 joinable 的一旦分离就不允许再使用 pthread_join// pthread_join(tid, nullptr); // 这里如果尝试使用 pthread_join 会引发错误// 获取主线程IDstring mainID changeID(pthread_self()); // 主线程IDwhile (1){// 输出主线程的信息 由于新线程已经被分离其ID实际上已经不再有效只是为了展示。cout main running..., mainID: mainID , new threadID: changeID(tid) endl;sleep(1);}return 0; } 线程ID及地址空间布局  pthread_create函数会产生一个线程ID存放在第一个参数指向的地址中。该线程ID和前面说的线程ID不是一回事。 前面讲的线程ID属于进程调度的范畴。因为线程是轻量级进程是操作系统调度器的最小单位所以需要一个数值来唯一表示该线程。 pthread_create函数第一个参数指向一个虚拟内存单元该内存单元的地址即为新创建线程的线程ID属于NPTL线程库的范畴。线程库的后续操作就是根据该线程ID来操作线程的。 用户级线程线程ID值就是库中结构体(TCB)对象的地址
http://www.hkea.cn/news/14257711/

相关文章:

  • 网站推广具体内容简要说明seo牛人
  • 福州市交通建设集团有限公司网站阿里ace wordpress
  • 无锡专业做网站公司wordpress插件太大
  • 网站设计英文翻译网站建设的时候如何上传图片
  • 2019建设什么网站好运营深圳英文网站建站
  • 龙华网站建设方案书例文建设部中国建造师网查询
  • 搭建网站的六个基本步骤流程如何制作3d效果图
  • 医院网站可以自己做吗百度竞价托管外包代运营
  • 网站建设及安全管理建一个信息 类网站
  • 晋中市两学一做网站wordpress4.6 中文
  • 一个人做网站原型天津做网站的企业
  • 网站推广链接怎么做杭州恒彩装饰公司怎么样
  • 高端网站建设公沈阳黑酷做网站建设优化公司怎么样
  • 电子商务网站建设题目个人网页模板关于爱国
  • 龙岩房产网河南企业网站优化
  • 深圳网站建设迈大学一学一做视频网站
  • 友链网站降权手机电视直播网站大全
  • 内部网站开发软件网页制作平台哪家好
  • 神华两学一做网站seo推广学院
  • 微信网站建设定制北京网站定制流程
  • 深圳做网站开发费用wordpress如何进入仪表盘
  • 酷炫网站源码营销技巧在线观看
  • 有哪些免费推广网站重庆企业网站推广策略
  • 国际网站平台有哪些营销型门户网站建设
  • 博物馆网站页面设计说明重庆建网站的公司集中在哪里
  • 来宾网站建设网址百度刷排名
  • 无忧建站网络工程师是干嘛的
  • 优秀的网站建设推荐超炫的网站模板
  • 安徽省建设厅网站打不开宽带公司排名
  • 课程网站建设的步骤义乌网页设计公司