线程ID
认识线程ID
怎么查看一个线程的ID呢?
线程库 NPTL 提供了 pthread_ self 函数, 可以获得线程自身的 ID;
不知道的可以看下面文章中的pthread_self()即可;【Linux】线程基本概念,线程控制-CSDN博客
void *Run(void *args)
{
cout << (char *)args << " TID: " << pthread_self() << endl;
sleep(5);
}
int main()
{
pthread_t tid;
pthread_create(&tid, nullptr, Run, (void *)"thread -1");
cout << "main thread TID :" << pthread_self() << endl;
sleep(5);
return 0;
}
运行结果:
pthread_ create 函数会产生一个线程 ID, 存放在第一个参数指向的地址中。
该线程 ID 和前面说的线程 ID (LWP)不是一回事。从图中可以很明显的看到LWP不等于TID;
- LWP:属于进程调度的范畴。 因为线程是轻量级进程, 是操作系统调度器的最小单位, 所以需要一个数值来唯一表示该线程;
- TID:pthread_t 类型的线程 ID, 本质就是一个进程地址空间上的一个地址。
给用户提供的线程ID,不是内核中的LWP,而是自己维护的一个唯一值,这个维护是pthread库维护的;
将TID转换成十六进程打印出来,我们可以知道ID其实是一个地址;
理解库
一个进程在创建多线程之前,首先我们在执行pthread_create之前,这个库被加载到内存并映射到进程的地址空间;
库如何对线程进程管理呢?先描述,在组织
所谓的先描述就是在库中创建描述线程相关结构体字段属性;在组织就是"数组";
所以未来我们只要找到线程控制块的地址,就能访问到线程的所有的属性;
Linux线程 = pthread库中线程的属性集 + LWP(1:1);
所以tid本质就是线程属性集合的起始虚拟地址;
封装线程
首先我们先写一下封装后的线程,可以调用函数,这个函数有功能:
下面我们在根据start(),stop(),join()来写;
start()
start():在start中我们要有用pthread_create来创建一个线程;其中线程的执行函数routine里面要执行的任务我们用回调函数来写:
定义:
线程要执行的方法:
using func_t = function<void()>;
类似于 typedef function<void()> func_t ;
typedef void (*func_t)(const string &name); // 函数指针类型
注意:因为routine是类内的成员方法,所以routine隐含了一个参数:this指针(Thread * this),这样就不满足void *(*__start_routine)(void *)了,可以直接把routine加上static,这样routine属于类,就不属于对象了,参数就没有this指针了;但是这样这里就不能直接调用类内的回调函数了,所以我们就要把当前对象传进来;
Thread *self = static_cast<Thread *>(args); int n = ::pthread_create(&_tid, nullptr, routine,this);
stop()
stop():在stop中我们要先判断是否是运行状态,如果是就会进行stop,而stop的做法就是pthread_cancel(取消)当前进程;最后更改当前的状态;
join()
join():pthread_join其实就是线程等待;
加锁
主要函数完成后就是对细节内容进行修改即可;
完整代码:
-
#pragma once #include <iostream> #include <string> #include <pthread.h> #include <functional> #include <unistd.h> #include <cstring> #include <cerrno> using namespace std; // 线程要执行的方法 // using func_t = function<void()>; // 就类似于 typedef function<void()> func_t ; class ThreadData { public: ThreadData(const string &name,pthread_mutex_t*lock):_name(name),_lock(lock) {} public: string _name; pthread_mutex_t*_lock; }; typedef void (*func_t)(ThreadData *td); // 函数指针类型 class Thread { public: void Excute() { _isrunning = true; _func(_td); } public: Thread(const string &name, func_t func,ThreadData*td) : _name(name), _func(func),_td(td) { } ~Thread() { } string status() { if (_isrunning) return "running"; return "sleep"; } static void *routine(void *args) { Thread *self = static_cast<Thread *>(args); self->Excute(); return nullptr; } bool start() { int n = ::pthread_create(&_tid, nullptr, routine,this); //::强度了使用标准库中的方法 if (n == 0) { return true; } return false; } void stop() { if (_isrunning) { pthread_cancel(_tid); _isrunning = false; } } void join() { if (!_isrunning) { pthread_join(_tid, nullptr); } } string Name() { return _name; } private: pthread_t _tid; string _name; bool _isrunning; func_t _func; // 线程要执行的回调函数 ThreadData *_td; };
以上就是线程ID和封装线程的全部内容,希望有所帮助!!!
标签:name,void,Linux,线程,func,pthread,ID From: https://blog.csdn.net/weixin_74116463/article/details/143176536