一篇带你完全掌握线程的博客

  前言:最近一直在疯狂学习,之前也不太了解线程,现在基本都掌握了。如果你之前也不知道线程,也不知道进程和线程的区别等等,这一篇博客带你完全掌握,不掌握不要钱,哈哈哈!

  一、线程概念

   介绍概念之前,先画个图吧,依旧是全博客园最丑图,不接受反驳!

  

  

  简单说明一下:进程在其内部创建线程,线程有自己的PCB,但没有独立的地址空间。

  线程和进程具有以下特征和区别:

  LWP:light weight process 轻量级的进程,本质仍是进程(在Linux环境下)

  进程:独立地址空间,拥有PCB

        线程:也有PCB,但没有独立的地址空间(共享)

        区别:在于是否共享地址空间。         独居(进程);合租(线程)。

        Linux下:          线程:最小的执行单位(CPU分配时间轮片是通过线程来实现的)

                                    进程:最小分配资源单位,可看成是只有一个线程的进程

  参考:《Linux内核源代码情景分析》 ----毛德操

  二、线程共享资源  

    1.文件描述符表

         2.每种信号的处理方式

         3.当前工作目录

         4.用户ID和组ID

         5.内存地址空间 (.text/.data/.bss/heap/共享库)

  三、线程非共享资源

   1.线程id

         2.处理器现场和栈指针(内核栈)

         3.独立的栈空间(用户空间栈)

         4.errno变量

         5.信号屏蔽字

         6.调度优先级

  四、线程的优缺点

    优点:     1. 提高程序并发性        2. 开销小        3. 数据通信、共享数据方便

         缺点:     1. 库函数,不稳定        2. 调试、编写困难、gdb不支持          3. 对信号支持不好

         优点相对突出,缺点均不是硬伤。Linux下由于实现方法导致进程、线程差别不是很大。

  五、线程相关函数

  在学习线程函数之前,再说点题外话。类Unix系统中,早期是没有“线程”概念的,80年代才引入,借助进程机制实现出了线程的概念。因此在这类系统中,进程和线程关系密切。所以可以将线程相关函数与进程函数进行对比学习。

  •   pthread_self函数

  功能:获取线程ID。其作用对应进程中 getpid() 函数。

  原型:pthread_t pthread_self(void);

  返回值:成功:0;       失败:无!

  线程ID:pthread_t类型,本质:在Linux下为无符号整数(%lu),其他系统中可能是结构体实现

       线程ID是进程内部,识别标志。(两个进程间,线程ID允许相同)  

  •   pthread_create函数 

   功能:创建一个新线程。                   其作用,对应进程中fork() 函数。

  原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

  返回值:成功:0;       失败:错误号         -----Linux环境下,所有线程特点,失败均直接返回错误号。

  参数说明:

  pthread_t:当前Linux中可理解为:typedef  unsigned long int  pthread_t;

  参数1:传出参数,保存系统为我们分配好的线程ID

       参数2:通常传NULL,表示使用线程默认属性。若想使用具体属性也可以修改该参数。

       参数3:函数指针,指向线程主函数(线程体),该函数运行结束,则线程结束。

       参数4:线程主函数执行期间所使用的参数。跟参数三关联。

  注意:链接线程库 -lpthread

  写一个简单程序,演示这两个函数用法:

  

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>

void *tfn(void *arg)
{
    printf("child thread%lu
",pthread_self());
    return NULL;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,tfn,NULL);
    sleep(1);
    printf("main thread:%lu
",pthread_self());
    
    return 0;
}
View Code

  编译:gcc pthread_cre.c -lpthread,记得链接线程库 -lpthread

  •    pthread_exit函数

  功能:将单个线程退出 相当于exit

  原型:void pthread_exit(void *retval);

  参数:retval表示线程退出状态,通常传NULL

  •   pthread_join函数

  功能:阻塞等待线程退出,获取线程退出状态              其作用,对应进程中 wait()、waitpid() 函数。

  原型:int pthread_join(pthread_t thread, void **retval);

  参数:thread:线程ID (【注意】:不是指针);retval:存储线程结束状态。

  •   pthread_detach函数

  功能:实现线程分离 线程独有的,没有进程的相关函数与之对应

  原型:int pthread_detach(pthread_t thread);

  线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后,其退出状态不由其他线程获取,而直接自己自动释放。网络、多线程服务器常用。

  重点:分离状态的线程就不需要回收了!!!重要的事情说三遍,三遍,三遍!!!

  •   pthread_cancel函数

  功能:杀死(取消)线程                         其作用,对应进程中 kill() 函数。

  原型:int pthread_cancel(pthread_t thread);

  【注意】:线程的取消并不是实时的,而有一定的延时。需要等待线程到达某个取消点(检查点)。

   六、控制原语对比

  就是就是将进程相关函数与线程函数,进行对比来记忆:

  进程                        线程

     fork                     pthread_create

     exit                     pthread_exit

     wait                    pthread_join

     kill                       pthread_cancel

     getpid                pthread_self              

  总结:欢迎评论,交流与学习。

  

原文地址:https://www.cnblogs.com/liudw-0215/p/9682962.html