【Linux】线程ID、线程封装(详解)

线程ID

认识线程ID

怎么查看一个线程的ID呢?                                                                                                             

线程库 NPTL 提供了 pthread_ self 函数, 可以获得线程自身的 ID;
不知道的可以看下面文章中的pthread_self()即可;【Linux】线程基本概念,线程控制-优快云博客

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其实就是线程等待;

 加锁

主要函数完成后就是对细节内容进行修改即可;

完整代码:

  1. #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和封装线程的全部内容,希望有所帮助!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值