给公司做网站,wordpress加密视频播放器,西安网站建设培训中心,成都市建设学校网站一、理解线程id
首先我们要知道给用户提供的线程id不是内核里面LWP#xff08;轻量级进程id#xff09;#xff0c;而是pthread库自己维护的一个唯一值。 我们理解为什么线程id不是内核里面LWP#xff0c;因为用户没有权限使用内核里面的字段#xff0c;那是专门给OS管理…一、理解线程id
首先我们要知道给用户提供的线程id不是内核里面LWP轻量级进程id而是pthread库自己维护的一个唯一值。 我们理解为什么线程id不是内核里面LWP因为用户没有权限使用内核里面的字段那是专门给OS管理线程用的。
但是为什么要pthread库来帮我们用户维护用户级线程id呢
因为Linux内核根本就不存在线程的概念所谓用户口中的线程在Linux眼里就是轻量级进程之后理解不在赘述具体参考文章http://t.csdnimg.cn/jTGGP中pthread库介绍。
内核级理解 所以我们清楚的看到返回给用户的线程id就是一个线程控制块在虚拟地址空间的起始位置。
类比FILE对象其实就在c标准库中返回的是FILE*就是地址。
所以 pthread_join() 函数就是通过tid找到存在虚拟地址空间中的线程结构体对象把里面的退出信息拷贝出来返回。
操作系统内示意图 二、简单封装原生线程库
thread.hpp
#pragma once
#includepthread.h
#includeiostream
#includestring
using namespace std;namespace Thread
{//线程执行方法typedef void(*func_t)(const string name);class Thread{public://线程执行方法void Excute(){cout _name is running endl; _isrunning true;_func(_name);_isrunning false;}public:Thread(const string name, func_t func):_name(name),_func(func){cout create name done endl; }//线程执行回调方法//设成静态方法函数就不会自带this指针类型就匹配上了//但是此时就无法调类的回调函数在create函数中传参即可static void* ThreadRoutine(void* args){//获得当前线程对象Thread* self static_castThread*(args);//调用线程执行方法self-Excute();return nullptr;}bool Start(){int n ::pthread_create(_tid, nullptr, ThreadRoutine, this);if (n ! 0)return false;return true;}string Status(){if(_isrunning) return running;else return sleep;}string GetName(){return _name;}void Stop(){if(_isrunning true){::pthread_cancel(_tid);_isrunning false;cout _name stop endl; }}void Join(){if(!_isrunning){::pthread_join(_tid, nullptr);cout _name join done endl; }}~Thread(){}private:string _name;pthread_t _tid;bool _isrunning false;func_t _func; //线程执行的回调函数};
}
main.cc
#includeiostream
#includethread.hpp
#includeunistd.h
#includevector
using namespace Thread;
using namespace std;void Print(const string name)
{int cnt 0;while(1){cout name is running, cnt: cnt endl;sleep(1);}
}const int num 10;int main()
{//创建线程vectorThread::Thread threads;for(int i 0; i num; i){string name thread- to_string(i 1);threads.emplace_back(name, Print);sleep(1);}//统一启动for(auto thread : threads){thread.Start();}sleep(10);//统一结束for(auto thread : threads){thread.Stop();}//统一回收for(auto thread : threads){thread.Join();}// Thread::Thread t(thread-1, Print);// t.Start();// cout t.GetName() status: t.Status() endl;// sleep(10);// cout t.GetName() status: t.Status() endl;// t.Stop();// sleep(1);// cout t.GetName() status: t.Status() endl;// t.Join();// cout join done endl;return 0;
}
三、线程的局部存储
对于一个全局变量一个进程中任意线程都能进行修改另外的线程也可以看到变化因为线程共享进程的大部分数据。
在LInux中我们用 __thread修饰全局变量只能修饰内置类型就能让全局变量在所有线程各有一份地址也不同这就能实现每一个线程都有属于自己的变量这就是线程的局部存储。