Linux--线程的分离、线程库的地点关系的明白、线程的简单封装(二) ...

科技颠覆者  论坛元老 | 2024-6-26 15:57:19 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 2067|帖子 2067|积分 6201

线程系列:
线程的认识:讲解线程的概念和线程的根本控制
  线程的分离

线程分离是指将一个线程从主线程中分离出来,使其能够独立运行。当一个线程被设置为分离状态时,它结束时系统会自动回收其资源,而不必要其他线程利用pthread_join()函数来等候其结束并手动回收资源。
   设置线程分离的方法
利用pthread_detach()函数:在线程创建后,可以通过调用pthread_detach()函数来将线程设置为分离状态。这个函数黑白阻塞式的,即调用后不会阻塞当前线程的执行。
在创建线程时设置分离属性:另一种方法是在创建线程时,通过pthread_create()函数的第二个参数(线程属性)来设置线程为分离状态。这种方法在创建线程时即指定了其分离属性,效率相对较高。
  1. void* threadrun(void* args)
  2. {
  3.     string name = static_cast<const char *>(args);
  4.     while(true)
  5.     {
  6.         sleep(1);
  7.         cout<<"this is new thread:"<<name<<endl;
  8.     }
  9. }
  10. int main()
  11. {
  12.         pthread_t tid;
  13.     pthread_create(&tid, nullptr, threadrun, (void *)"thread 1");
  14.     cout << "main thread wait block" << std::endl;
  15.     pthread_join(tid, nullptr);
  16.     cout << "main thread wait return"<<endl;
  17. }
复制代码

利用分离函数后:

再加个有限时间的循环看看:

对线程分离明白:虽然新线程与主线程已经分离了,但它们仍然是同一历程中的执行流,如果步伐利用时出现异常时(新线程或者主线程),那么两个步伐都会终止;或者说主线程结束了,实际上就代表历程结束了;所以线程的分离仍然是在历程中进行的,受历程的影响;
何时利用:当线程完成任务后不必要与其结果交付时;当线程在后台运行且不必要与主线程进行同步进行时;
注意:分离线程无法重新连接!而可连接线程可以分离,当只有在尚未开始运行之前
明白线程库的地点关系



线程栈

线程栈是与线程紧密相关的内存区域,用于存储线程的局部变量、函数调用的返回地点以及线程的执行上下文等信息。每个线程都有自己独立的栈空间,这保证了线程之间的数据是隔离的,从而制止数据竞争和线程安全问题。
  1. #include<iostream>
  2. using namespace std;
  3. #include<pthread.h>
  4. #include<unistd.h>
  5. void *threadrun1(void *args)
  6. {  
  7.     std::string name = static_cast<const char *>(args);
  8.     int g_val=100;
  9.     while(true)
  10.     {
  11.         sleep(1);
  12.         printf("%s, g_val: %lu, &g_val: %p\n", name.c_str(), g_val--, &g_val);
  13.     }
  14.     return nullptr;
  15. }
  16. void *threadrun2(void *args)
  17. {
  18.     std::string name = static_cast<const char *>(args);
  19.     int g_val=100;
  20.     while(true)
  21.     {
  22.         printf("%s, g_val: %lu, &g_val: %p\n", name.c_str(), g_val--, &g_val);
  23.         sleep(1);
  24.     }
  25.     return nullptr;
  26. }
  27. int main()
  28. {
  29.     pthread_t tid1;
  30.     pthread_t tid2;
  31.     pthread_create(&tid1, nullptr, threadrun1, (void *)"thread 1");
  32.     pthread_create(&tid2, nullptr, threadrun2, (void *)"thread 2");
  33.     pthread_join(tid1, nullptr);
  34.     pthread_join(tid2, nullptr);
  35. }
复制代码
通过两个新线程都创建一个局部变量(变量名相同),比力它们的地点;

可以看到g_val在各自线程是不一样的,地点也是差别的;
线程局部存储(TLS)

线程局部存储(TLS)是一种机制,允许每个线程拥有自己的私有数据副本,纵然差别线程执行相同的代码,TLS变量与通例全局变量是差别的,因为每个线程堆TLS变量的访问都是独立的。
一样平常实用于:


  • 线程特定数据:当某些数据只对特定线程有意义,并且必要在线程内保持状态时,可以利用线程局部存储。
  • 全局状态隔离:通过将全局状态分离为每个线程的私有副本,可以进步并发性能,制止线程间的数据竞争。
  • 线程上下文保存:线程局部存储也可用于保存当前执行线程的上下文信息,如用户身份验证信息、数据库连接等。
注意:
线程局部存储变量通常只能用于具有静态或线程存储期的变量,不能用于自动或动态分配的变量。利用线程局部存储时必要谨慎管理内存,制止内存泄漏或无效访问等问题。
线程的封装

线程的封装通常指的是将线程的创建、执行、同步、资源管理等逻辑封装到一个类或对象中,以便更好地组织代码,进步代码的可读性和可维护性
封装线程可以隐藏线程的复杂性,使得其他部分的代码可以更加简便地与线程进行交互。
下面看具体代码:
Thread.hpp:对线程的封装
  1. #ifndef __THREAD_HPP__
  2. #define __THREAD_HPP__
  3. #include<iostream>
  4. #include<string>
  5. #include<pthread.h>
  6. #include<functional>
  7. #include<unistd.h>
  8. using namespace std;
  9. namespace ThreadMdule
  10. {
  11.         //通过模板类可调用一切任何对象
  12.     template<typename T>
  13.     using func_t = std::function<void(T&)>;
  14.     template<typename T>
  15.     class Thread
  16.     {
  17.     public:
  18.         void Excute()
  19.         {
  20.             _func(_data);
  21.         }
  22.         Thread(func_t<T> func, T data, const std::string &name="none-name")
  23.             : _func(func), _data(data), _threadname(name), _stop(true)
  24.         {}
  25.         static void* threadroutine(void* args)
  26.         {
  27.             Thread<T>* self=static_cast<Thread<T>*>(args);
  28.             self->Excute();
  29.             return nullptr;
  30.         }
  31.         
  32.         bool start()
  33.         {
  34.             int n=pthread_create(&_tid,nullptr,threadroutine,this);
  35.             if(!n)
  36.             {
  37.                 _stop = false;
  38.                 return true;
  39.             }
  40.             else
  41.             {
  42.                 return false;
  43.             }
  44.         }
  45.         void Detach()
  46.         {
  47.             if(!_stop)
  48.             {
  49.                 pthread_detach(_tid);
  50.             }
  51.         }
  52.         void Join()
  53.         {
  54.             if(!_stop)
  55.             {
  56.                 pthread_join(_tid,nullptr);
  57.             }
  58.         }
  59.         string name()
  60.         {
  61.             return _threadname;
  62.         }
  63.         void Stop()
  64.         {
  65.             _stop = true;
  66.         }
  67.         ~Thread() {}
  68.     private:
  69.         pthread_t _tid;
  70.         std::string _threadname;
  71.         T _data;  
  72.         func_t<T> _func;
  73.         bool _stop;
  74.     };
  75. }
  76. #endif
复制代码
线程类中包罗了:线程名,数据,调用函数指针等;
通过start()函数来创建新线程:用到了函数threadroutinue,在函数中将函数成员_func(也就是具体函数的指针)利用了起来,就表示新线程的创建利用;
主函数的调用:
  1. void print(int &cnt)
  2. {
  3.     while (cnt)
  4.     {
  5.         std::cout << "hello I am myself thread, cnt: " << cnt-- << std::endl;
  6.         sleep(1);
  7.     }
  8. }
  9. const int num=3;
  10. int main()
  11. {
  12.     vector<Thread<int>> threads;
  13.     //创建新线程
  14.     for(int i=0;i<num;i++)
  15.     {
  16.         string name="thread"+to_string(i + 1);
  17.         threads.emplace_back(print,3,name);
  18.     }
  19.     //启动进程
  20.     for(auto& thread:threads)
  21.     {
  22.         thread.start();
  23.     }
  24.     //等待进程结束
  25.     for(auto& thread:threads)
  26.     {
  27.         thread.Join();
  28.         cout<<"wait thread done,thread is: "<<thread.name()<<endl;
  29.     }
  30.     return 0;
  31. }
复制代码

这样就是对线程的简单封装;
通过封装线程,我们可以更好地控制线程的创建、执行和烧毁过程,同时使得代码更加清晰和易于维护。
此外,封装还可以资助我们添加额外的功能,好比线程池的集成、异常处理、线程同步等。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

科技颠覆者

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表