【Linux学习】多线程——线程控制 | 线程TCB

这篇具有很好参考价值的文章主要介绍了【Linux学习】多线程——线程控制 | 线程TCB。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🐱作者:一只大喵咪1201
🐱专栏:《Linux学习》
🔥格言:你只管努力,剩下的交给时间!
【Linux学习】多线程——线程控制 | 线程TCB

🧰线程控制

Linux内核中并不存在线程的概念,我们程序员是通过库来使用线程的,这个库是POSIX线程库,是由原生线程库提供的,它遵守POSIX标准,就像之前学过的System V标准一样。POSIX线程库有以下几个特点:

  1. 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头的。
  2. 要使用这些函数库,要通过引入头文<pthread.h>。
  3. 链接这些线程函数库时要使用编译器命令的“-lpthread”选项。

🎴线程创建

系统调用接口:

【Linux学习】多线程——线程控制 | 线程TCB

  • pthread_t* thread:输出型参数,将线程的tid值放入到我们外部创建好的pthread_t 类型的变量中。
  • 第二个参数:用来设置线程属性,一般情况下设置成nullptr,等用到的时候再详细讲解。
  • void* (*start_routine)(void *):函数指针,这是一个回调函数,该函数的内容就是新线程要执行的。
  • void* arg:回到函数的参数。
  • 返回值: 线程创建成功返回0,不成功返回错误码。

一般情况下,新线程的创建是不会失败的,万一失败了,也不会设置errno,因为errno是一个全局变量,某个线程改变了这个变量会对其他线程造成影响,所以直接将错误码返回即可。

  • 在编译的时候,必须指定线程库,使用-l pthread选项。

接下来用这个接口创建一批线程:

#define NUM 10

void* start_routine(void* args)
{
    sleep(1);
    string name = (char*)(args);
    while(1)
    {
        cout<<"new thread name: "<<name<<endl;
        sleep(1);
    }
}

int main()
{
    //创建一批线程
    for(size_t i = 0; i < NUM; ++i)
    {
        pthread_t tid;
        char buffer[64];
        snprintf(buffer,sizeof buffer,"thread %d",i+1);
        pthread_create(&tid,nullptr,start_routine,(void*)buffer);
    }

    while(1)
    {
        cout<<"----create success----"<<endl;
        sleep(1);
    }
    return 0;
}

创建10个线程,让它们同时运行,并且给每个线程编号,新线程死循环打印各自的线程名字,新线程在延时1秒后开始执行。

【Linux学习】多线程——线程控制 | 线程TCB
将上诉代码运行起来后,查看线程,可以看到一共有11个线程,其中1个主线程,10个新线程。

【Linux学习】多线程——线程控制 | 线程TCB
但是运行结果中,10个线程都是线程10,其他9个线程并没有出现,这是什么原因呢?

【Linux学习】多线程——线程控制 | 线程TCB

  • 新线程中首先要延时1秒钟,然后才开始执行代码,在它延时的过程中,主线程一直在跑。
  • 主线程中的名字缓冲区会被覆盖,最终只有"thread 10"。
  • 当10个新线程开始执行时,需要去缓冲区中拿数据(缓冲区所有线程共享),所以拿到的都是"thread 10"。

上面代码中,本喵故意给新线程先延时了一秒钟,让主线程先跑,去覆盖缓冲区,如果不延时也有可能会出现上诉情况。

  • 主线程和新线程到底谁先执行是不确定的,是由操作系统的调度器决定的。

即使不给新线程延时,也有可能是主线程先运行,在时间片结束之前,同样会完成数据覆盖,导致新线程从缓冲区中只能读到最终的数据。

所以说,上面的代码是有问题的,我们需要保证每个线程都有自己独一无二的缓冲区。

class ThreadData
{
public:
    pthread_t _tid;
    char _name[64];
};

创建一个类,这个类中包括线程的tid以及名字的缓冲区。

【Linux学习】多线程——线程控制 | 线程TCB

  • 每个线程都在堆区new一个对象,来存放该线程的tid以及名字,然后将这个对象的地址传给新线程。
  • 新线程通过主线程传过来的指针找到属于它的结构体对象,然后使用里面的数据。

【Linux学习】多线程——线程控制 | 线程TCB
此时10个线程就都能正常运行了,不存在缓冲区的覆盖问题了,因为一个线程有一个缓冲区。

🎴线程结束

  1. return nullptr结束线程

【Linux学习】多线程——线程控制 | 线程TCB
当新线程执行到return的时候,就会结束。

  • 在线程中加了计数值,5秒后跳出循环,执行return,结束线程。

【Linux学习】多线程——线程控制 | 线程TCB
当计数值到了以后,新线程全部结束,只剩下主线程在执行。

  1. pthread_exit()结束线程

POSIX线程库专门提供了一个接口来结束线程:

【Linux学习】多线程——线程控制 | 线程TCB

  • 参数:返回线程结束信息,当前阶段设置成nullptr即可。

调用该接口的线程会结束。

【Linux学习】多线程——线程控制 | 线程TCB
同样,当计数值到了以后,新线程会调用该接口,然后就只剩下主线程了,新线程全部结束了。

注意:

不能使用exit()来结束线程,因为exit系统调用是争对进程的,调用该接口会让整个进程都结束掉。

🎴线程等待

和进程一样,线程也是需要等待的,如果不等待会造成内存泄漏,也就是结束掉的线程PCB不会被回收(类似僵尸进程),但是我们看不到没有回收的现象。

系统调用:

【Linux学习】多线程——线程控制 | 线程TCB

  • pthread_t thread:要等待的线程tid。
  • void** retval:线程结束信息返回,这是一个输出型参数。
  • 返回值:等待成功返回0,等待失败返回错误码。

【Linux学习】多线程——线程控制 | 线程TCB
主线程中并没有延时,它执行的速度是很快的。在新线程中需要进行计数,所以执行速度会慢很多。

【Linux学习】多线程——线程控制 | 线程TCB

可以看到,主线程在执行到线程等待的时候,会阻塞等待,不再往下执行,直到所有线程都等待成功才会继续向下执行。

所以说,线程等待是阻塞式等待

线程返回值

线程等待和进程等待一样,主要有两个作用:

  • 获取线程退出信息。
  • 回收线程PCB资源,防止内存泄漏。

上面线程等待的代码中并没有获取线程退出的相关信息,那么该如何获取线程退出的相关信息呢?

【Linux学习】多线程——线程控制 | 线程TCB

  • 新线程在结束的时候会返回一个void*类型的指针。
  • 在pthread线程库中,有一个void类型的指针变量来接收从线程中返回的void指针。
  • 指针变量和指针是有区别的,指针变量会开辟空间,里面存放的是指针。
  • 指针就是地址,是数字,不会开辟空间。

如上图中代码所示,将整形数字10强转成void*类型,然后返回。

  • 现在面临的问题就是怎么从pthread线程库中拿到从线程中返回的void*指针。

【Linux学习】多线程——线程控制 | 线程TCB
在主线程的栈区中有一个void类型的指针变量,新线程中返回的void类型指针最终会放到这个ret中。

  • pthread线程库中有一个void** 类型的二级指针变量retval。
  • pthread_join()系统调用将主线程中void*类型的指针变量的地址传给了pthread线程库中的二级指针变量,此时主线程就和线程库建立了联系。
  • 将新线程中返回到线程库中的void*指针变量中的返回值,通过这种联系放到主线程中指针变量中----也就是 *retval = ret。

这样,我们就可以成功的获取到新线程退出时的返回信息了,桥梁就是pthread_join()系统调用。

pthread_join()系统调用中,之所以传的是二级指针,是为了在pthread库中能够找到主线程中一级指针变量 void * ret。

【Linux学习】多线程——线程控制 | 线程TCB
在线程等待时,传入ret的二级指针获取线程退出信息。

  • 由于Linux中void* ret是8个字节,接收到的线程退出信息10也是一个void*类型的。
  • 我们要想看到这个值,需要将它转换成整数,所以必须转成longlong类型,也是8个字节,如果转成int的话会有精度损失从而会报错。

【Linux学习】多线程——线程控制 | 线程TCB
可以看到,每个线程在退出时的退出信息都被主线程接收到了,由于所有线程的退出信息都是10,所以接收到的也都是10。

【Linux学习】多线程——线程控制 | 线程TCB
通过pthread_exit()同样可以将线程的退出信息返回到pthread的线程库中,然后再通过线程等待接口拿走这个退出信息。

  • 在结构体中增加一个线程编号信息,每创建成功一个线程都给它一个编号。
  • 新线程在退出的时候返回各自的编号。
  • 线程等待代码不变,和上面一样。

【Linux学习】多线程——线程控制 | 线程TCB

此时我们就成功获得了各个线程在退出时候返回的编号,也就是获得了线程的退出信息。

整数都可以返回,更别说一个真正的地址了,可以将要返回的信息放在数组中,然后返回数组地址

  • 在学习进程等待的时候,我们不仅可以获得进程的退出信息,还能获得进程的退出信号,但是在线程退出时就没有获得线程退出信号,这是为什么呢?
  • 因为信号是发给进程的,整个进程都会被退出,线程要退出信号也没有意义了。
  • 而且pthread_join默认是能够等待成功的,并不考虑异常的问题,异常是进程要考虑的事,线程不用考虑。

线程取消(线程结束的一种方式)

线程取消的接口:

【Linux学习】多线程——线程控制 | 线程TCB

  • 参数:要取消的线程tid。
  • 返回值:取消成功返回0,失败返回错误码。
  • 只有运行起来的线程才能被取消。

【Linux学习】多线程——线程控制 | 线程TCB
在主线程中,新线程被创建后,取消一半的线程,然后继续进行线程等待。

【Linux学习】多线程——线程控制 | 线程TCB
10个线程被创建后就会跑起来。

  • 前五个线程被取消了,线程等待直接成功,不用再阻塞,被取消的线程等待成功后的返回值是-1,并不是我们设定的线程编号。
  • 未被取消的后五个线程,仍然阻塞等待,等待成功后返回的是我们设定的线程编号。

所以说,如果一个线程是被取消结束的,它的退出码就是-1。它其实是一个宏定义:PTHREAD_CANCELED。

线程取消也是一种线程结束的方式,放在这里是为了能够通过线程等待看线程退出的退出码。

🎴线程分离

线程的tid也可以通过接口获得,就像获得pid一样,获取tid的接口:

【Linux学习】多线程——线程控制 | 线程TCB
这个接口也是POSIX线程库提供的,哪个线程调用该接口就会返回哪个线程的tid。

  • 默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法释放资源,从而造成系统泄漏。

但是这样主线程就需要阻塞式等待线程的释放,主线程什么都干不了。能不能像进程那样不需要阻塞式等待(将SIGCHID信号设置为忽略),等新线程结束以后自动释放呢?

  • 尤其是不需要关心线程返回值的时候,join是一种负担。

当然可以,将需要自动释放的线程设置成分离状态,将线程设置成分离状态意味着不需要主线程再关心该线程的状态,它会自动释放。

  • joinable和分离是冲突的,一个线程不能既是joinable又是分离的。

线程分离的接口:

【Linux学习】多线程——线程控制 | 线程TCB

  • 参数:要分离的线程tid。
  • 返回值:成功返回0,不成功返回错误码。
  • 可以是线程组内其他线程对目标线程进行分离,也可以是线程自己分离。自己分离自己就需要使用接口获取到自己的tid。

线程分离后,如果主线程仍然等待该线程,就会等待失败,返回错误码

新线程中分离自己:

void* start_routine(void* args)
{
    string name = static_cast<const char*>(args);
    size_t cnt = 5;
    pthread_detach(pthread_self());//线程分离
    while(cnt--)
    {
        cout<<"new thread name: "<<name<<", cnt: "<<cnt<<endl;
        sleep(1);
    }
    pthread_exit(nullptr);
}

int main()
{
    //创建新线程
    pthread_t tid;
    pthread_create(&tid,nullptr,start_routine,(void*)"thread one");
    cout<<"main thread tid: 0x"<<(void*)pthread_self()<<endl;

    //线程等待
    int n = pthread_join(tid,nullptr);
    cout<<"error: "<<n<<"->"<<strerror(n)<<endl;

    return 0;
}

在新线程中分离线程。
【Linux学习】多线程——线程控制 | 线程TCB
不是说线程分离了再进行线程等待就会失败吗?怎么上面的运行结果仍然是等待成功呢?

  • 因为主线程先被调度,在新线程被创建但是没有执行的时候主线程就开始等待新线程了。

所以当新线程将自己分离以后,主线程已经处于等待状态了,它不认为新线程被分离,还会继续等待,而且可以等待成功。

【Linux学习】多线程——线程控制 | 线程TCB
可以让主线程延时一段时间,保证新线程先执行,也就是保证线程分离发生在线程等待之前。

【Linux学习】多线程——线程控制 | 线程TCB
可以看到,此时主线程在进行线程等待的时候就会失败,而且返回错误码。

在主线程中分离新线程:

最为稳妥的办法就是在主线程中分离新线程:

【Linux学习】多线程——线程控制 | 线程TCB
在主线程中分离新线程,任何进行线程等待,并且主线程在一直运行。

【Linux学习】多线程——线程控制 | 线程TCB

  • 主线程等待新线程失败后直接返回错误码,然后接着向下运行,并不会阻塞。

在新线程运行结束以后,自动回收其PCB资源,只剩下主线程在运行。

  • 一个线程一旦被分离就不用再管这个线程了,在它运行结束的时候系统会自动回收,不会造成内存泄漏。

🧰C++多线程

我们知道,C++也是可以多线程编程的,而且提供了多线程的库,而无论什么编程语言,什么库,在Linux系统上的多线程本质上都是对pthread原生线程库的封装

接下面本喵就模拟一下C++对线程库的封装,写一个小组件,同时也方便我们后面直接使用:

#define NUM 1024

class Thread;//前置声明

class Context//线程上下文
{
public:
    Context()
    :_this(nullptr)
    ,_args(nullptr)
    {}

    //成员变量
    Thread* _this;
    void* _args;
};

class Thread
{
public:
    //重命名函数对象
    typedef std::function<void*(void*)> func_t;
    
    //构造函数
    //传入新线程执行的函数,参数,以及新线程编号
    Thread(func_t func, void* args = nullptr, int number = 0)
        :_func(func)
        ,_args(args)
    {
        //格式化线程名
        char buffer[NUM];
        snprintf(buffer,sizeof (buffer),"thread-%d",number);
        _name = buffer;
        //创建线程
        Context* ctx = new Context();
        ctx->_this = this;
        ctx->_args = _args;
        int n = pthread_create(&_tid,nullptr,start_routine,ctx);
    }

    void* run(void* args)
    {
        return _func(args);
    }

    //由于调用成员函数有隐藏的this指针,所以使用static修饰
    //void* start_routine(this, void* args)
    static void* start_routine(void* args)
    {
        Context* ctx = static_cast<Context*>(args);//安全的类型转换
        void* ret = ctx->_this->run(ctx->_args);
        delete ctx;
        return ret;
    }

    //线程等待
    void join()
    {
        int n = pthread_join(_tid,nullptr);
        assert(n==0);
        (void)n;
    }
private:
    std::string _name;
    func_t _func;
    void* _args;
    pthread_t _tid;
};

【Linux学习】多线程——线程控制 | 线程TCB

  • 在调用start_routine成员函数的时候,会隐藏一个this指针。
  • 而pthread_create中的函数指针只有一个形参,为了消除这个指针,用static修饰新线程调用的函数。

此时就面临一个新的问题,在static函数内,需要调用类内的成员函数run(),但是没有this指针无法调用。

  • 创建一个上下文类,里面放线程类的this指针,在static函数内通过这个指针来调用类内的成员函数run()。

测试代码:

void* thread_run(void* args)
{
    string work_type=static_cast<const char*>(args);
    while(1)
    {
        cout<<"新线程:"<<work_type<<endl;
        sleep(1);
    }
}

int main()
{
    unique_ptr<Thread> thread1(new Thread(thread_run,(void*)"thread1",1));
    unique_ptr<Thread> thread2(new Thread(thread_run,(void*)"thread2",2));
    unique_ptr<Thread> thread3(new Thread(thread_run,(void*)"thread3",3));

    thread1->join();
    thread2->join();
    thread3->join();


    return 0;
}

【Linux学习】多线程——线程控制 | 线程TCB
可以看到,成功创建3个新线程,并且在不停运行。

这里仅是语言层面对线程库的封装。

🧰线程库中的TCB

🎴线程tid

前面多次见过线程的tid值,但是一直不知道它是什么,现在来揭开它的神秘面纱。

【Linux学习】多线程——线程控制 | 线程TCB
新线程和主线成都打印新线程的tid,并且主线程也打印自己的tid。

【Linux学习】多线程——线程控制 | 线程TCB

  • 主线程和新线程打印的新线程tid的值都是一样的。
  • 而且tid的值是一个地址。

【Linux学习】多线程——线程控制 | 线程TCB
我们知道,Linux内核中是没有线程概念的,也没有对应的TCB结构。

  • 用户创建线程时使用的是POSIX线程库提供的接口。
  • 线程库中会调用clone()系统调用接口,在内核中创建线程复用的PCB结构。
  • 这些轻量级进程共用一个进程地址空间。

系统中肯定不只一个线程存在,大量的线程势必要管理起来,管理的方式同样是先描述再组织。既然Linux内核中只有轻量级进程的PCB,那么描述线程的TCB结构就只能存在于线程库中

所以pthread线程库中就会维护很多TCB结构:

//伪代码
struct pthread
{
	//线程局部存储
	//线程栈
	//....
}

线程库中的TCB里,存放着线程的属性,这里的TCB被叫做用户级线程

  • Linux线程方案:用户级线程以及用户关心的线程属性在线程库中,内核提供线程执行流的调度。
  • Linux 用户级线程 : 内核轻量级进程= 1 :1

一个线程的所有属性描述是由两部组成的,一部分就是在pthread线程库中的用户级线程,另一部分就是Linux中的轻量级进程,它们俩的比例大约是1比1。

【Linux学习】多线程——线程控制 | 线程TCB

  • pthread线程库从磁盘上加载到内存中后,通过页表再将虚拟地址空间和物理地址映射起来。
  • 线程库最终是映射在虚拟地址空间中的共享区中的mmap区域。

既然线程库是映射在共享区的,那么线程库所维护的TCB结构也就一定在共享区。

【Linux学习】多线程——线程控制 | 线程TCB

如上图所示,将映射到共享区的动态线程库放大。

  • 线程库中存在多个TCB结构来描述线程。
  • 每个TCB的地址就是线程id。

线程tid的本质就是虚拟地址共享区中TCB结构体的地址

  • 线程的栈也在共享区中,而不在栈中。
  • 虚拟地址空间中的栈是主线程的栈,共享区中动态库中的栈是新线程的栈。

所以说,线程的栈结构是相互独立的,因为存在于不同的TCB中(主线程除外)

🎴线程局部存储(__thread)

在共享区线程库中的TCB里,有一个线程的局部存储属性,它是一个介于全局变量和局部变量之间线程特有的属性。

【Linux学习】多线程——线程控制 | 线程TCB
在主线程和新现在中同时打印全局变量g_val以及它的地址。

【Linux学习】多线程——线程控制 | 线程TCB
主线程和新线程打印的值都是一样的。

  • 说明主线程和新线程共用一个全局变量。

那如果此时新线程仍然想用这个变量名,但是又不想影响其他线程,也就是让这个全局变量独立出来,该怎么办呢?此时就可以使用线程的局部存储属性了。

【Linux学习】多线程——线程控制 | 线程TCB

  • 在全局变量g_val前面加__thread(两个下划线),此时这个全局变量就具有了局部存储的属性。

主线程和新线程同样打印这个全局变量,并且新线程将这个具有局部存储属性的全局变量不断加一。

【Linux学习】多线程——线程控制 | 线程TCB

  • 主线程和新线程打印出来的全局变量的地址不相同了,说明此时用的并不是同一个全局变量。
  • 新线程修改这个值,主线程不受影响。
  • 可以将全局变量或者static变量添加 __thread,设置位线程局部存储。
  • 此时每个线程的TCB中都会有一份该变量,相互独立,并不会互相影响。

🧰总结

有了进程的基础,线程有些地方可以进行类比,还是比较容易理解的。线程控制非常重要,而且在编程中经常使用到。文章来源地址https://www.toymoban.com/news/detail-454566.html

到了这里,关于【Linux学习】多线程——线程控制 | 线程TCB的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】多线程1——线程概念与线程控制

    📝 个人主页 :超人不会飞) 📑 本文收录专栏 :《Linux》 💭 如果本文对您有帮助,不妨 点赞、收藏、关注 支持博主,我们一起进步,共同成长! 💭理解线程需要和进程的概念紧密联系。 线程是一个执行分支,执行粒度比进程更细,调度成本更低; 进程是分配系统资源的

    2024年02月12日
    浏览(21)
  • Linux 多线程( 进程VS线程 | 线程控制 )

    进程是资源分配的基本单位。 线程是OS调度的基本单位。 线程共享进程数据,但也拥有自己的一部分数据: 线程ID 一组寄存器 ,用来保存每个线程的上下文数据,让每个线程能够合理调度。 栈 ,每个线程入栈出栈产生的临时变量必须保存到每个线程的私有栈中,所以栈对于

    2024年02月07日
    浏览(33)
  • 【Linux】多线程 --- 线程概念 控制 封装

    从前种种,譬如昨日死。从后种种,往如今日生。 1.1 进程资源如何进行分配呢?(地址空间+页表) 1. 首先我们来看一个现象,当只有第一行代码时,编译是能通过的,但会报warning,当加了第二行代码时,编译无法通过,报error。 第一行代码能编过的原因是权限缩小,虽然

    2024年02月03日
    浏览(48)
  • 【Linux】多线程01 --- 理解线程 线程控制及封装

    🍎 作者: 阿润菜菜 📖 专栏: Linux系统编程 在Linux中其实没有真正线程的概念,在Linux中线程的概念其实就是进程内部的一个执行流。在宏观层面上理解,线程是执行流这句话放在任何一个OS上都没错,但落实到具体操作系统上,不同的OS多线程实现策略是不一样的,例如

    2024年02月07日
    浏览(40)
  • 『Linux』第九讲:Linux多线程详解(二)_ 线程控制

    「前言」文章是关于Linux多线程方面的知识,上一篇是 Linux多线程详解(一),今天这篇是 Linux多线程详解(二),讲解会比较细,下面开始! 「归属专栏」Linux系统编程 「主页链接」个人主页 「笔者」枫叶先生(fy) 「枫叶先生有点文青病」「每篇一句」 纵有千古,横有八荒

    2024年02月01日
    浏览(33)
  • Linux--线程-条件控制实现线程的同步

    1.条件变量 条件变量是线程另一可用的同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。 条件本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量,其他线程在获得互斥量之

    2024年02月05日
    浏览(31)
  • 多线程基础入门【Linux之旅】——上篇【线程控制,线程互斥,线程安全】

    目录 前文 回望页表 一,什么是线程 二,使用 pthread_create (线程创建) 三,线程控制 1 ,线程共享进程数据,但也拥有自己的一部分数据: 2, 线程  VS 进程优点 3,pthread_join(等待线程) 4,pthread_exit (线程终止) 5, pthread_cancel (线程取消) 6. pthread_t 类型 7.  pthread_detac

    2024年01月16日
    浏览(36)
  • Linux系统编程:线程控制

    目录 一. 线程的创建 1.1 pthread_create函数 1.2 线程id的本质 二. 多线程中的异常和程序替换 2.1 多线程程序异常 2.2 多线程中的程序替换 三. 线程等待 四. 线程的终止和分离 4.1 线程函数return 4.2 线程取消 pthread_cancel 4.3 线程退出 pthread_exit 4.4 线程分离 pthread_detach  五. 总结

    2024年02月11日
    浏览(32)
  • <Linux> 线程控制

    目录   一、线程资源的分配 (一)线程私有资源 (二)线程共享资源 二、原生线程库 三、线程控制接口 (一)线程创建 - pthread_create() 1. 一个线程  2. 一批线程 (二)线程等待 - pthread_join() (三)线程终止 - pthread_exit() 四、线程实操 五、线程控制接口补充 (一)关闭线

    2024年03月13日
    浏览(22)
  • Linux之线程控制

    目录 一、POSIX线程库 二、线程的创建 三、线程等待 四、线程终止 五、分离线程 六、线程ID:pthread_t 1、获取线程ID 2、pthread_t 七、线程局部存储:__thread 由于Linux下的线程并没有独立特有的结构,所以Linux并没有提供线程相关的接口。 而我们所说的,pthread线程库是应用层的

    2024年03月11日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包