浅析Linux下的线程

原创 2018年04月15日 18:51:03

一、线程


线程的概念:

  • 在一个程序里的执行路线就叫做线程,或者说线程是一个进程内部的执行流
  • 一个进程至少有一个执行流,也就是主线程
  • 线程和线程之间大部分资源都是共享的
Linux下的进程与线程
  • 图解:

这里写图片描述

线程和进程对比来看:

  • 线程在进程内部执行
  • 线程比进程执行流更小,执行粒度更小
  • 线程的切换比进程切换成本小
  • 线程的创建比进程轻量化很多,所以创建和释放成本都非常低,而且Linux下是没有具体的线程的,Linux内核同样用PCB来描述线程,只不过同组线程具有相同的pid(进程ID),所以Linux下的线程被看做是轻量化进程
  • 线程出错也相当于进程出错,也就是某个线程因为中断,异常等挂掉,该进程也会挂掉

进程内线程共享的资源:

  • 同一地址空间,代码段和数据段都是共享的,在一个程序内定义一个函数或者全局变量,该进程内的所有线程都可以调用该函数,访问该变量
  • 文件描述符表
  • 每种信号的处理方式(SIG_IGN、SIG_DFL或者自定义的信号处理函数)
  • 当前工作目录
  • 用户ID和组ID

各线程独享的资源

  • 私有栈:一个线程调用一个函数时,该函数内部的局部变量等都在该进程私有的栈空间内,其他线程无权访问
  • 独立上下文:线程被切换时,它的上下文数据都是自己独有的,等到被切换回来时上下文数据也会恢复,继续执行之前的程序
  • 信号屏蔽字
  • 线程ID(不同于进程ID,每个线程都有自己独有的标识符)等

线程控制

POSIX线程库
  • 绝大多数与线程相关的函数都是以”pthread_”开头的
  • 使用这些函数时,需要引入头文件”pthread.h”
  • 链接这些线程函数库时要使用编译器命令的”-lpthread”选项
创建线程

pthread_create函数

函数体:

        int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);  
thread:返回线程ID
attr:设置线程的属性,attr为NULL时表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码

错误检查:

  • 传统的一些函数是,成功返回0,失败返回-1,并且对全局变量errno赋值以指示错误
  • pthreads函数出错时不会设置全局变量errno(而大部分其他POSIX函数会这样做)。而是将错误代码通过返回值返回
  • pthreads同样也提供了线程内的errno变量,因为读取返回值要比读取线程内的errno变量的开销更小
线程终止

如果是只终止某个线程,而不终止整个进程,则有下面的三种方法

  • 线程调用的函数通过return返回,但对主线程不适用,从main函数调用return则相当于整个进程终止
  • 线程调用pthread_exit函数终止自己,注意线程调用的函数调用exit时,会使整个进程终止
  • 一个线程通过调用pthread_cancelt函数终结别的进程

pthread_exit函数

函数体:

      void pthread_exit(void *value_ptr);  
value_ptr:value_ptr不要指向一个局部变量,因为当其他线程得到这个返回指针时线程函数已经退出了
返回值:无返回值,和进程一样,线程结束的时候无法返回到它的调用者(自身)

pthread_cancel函数

函数体:

       int pthread_cancel(pthread_t thread);  
thread:线程ID
返回值:成功返回0,失败返回错误码
线程等待

一个线程退出后,其空间并不会自动释放,必须有另外一个线程来回收其资源,并且创建新的线程不会占用刚退出的线程的地址空间,

pthread_join函数

函数体:

     int pthread_join(pthread_t thread, void **value_ptr);  
thread:线程ID
value_ptr:它指向一个指针,后者返回线程的返回值
返回值:成功返回0,失败返回错误码
线程分离

线程在调用join方法时,进行的是阻塞式的等待,所以当我们不关心线程的返回值时,join方法是一种负担,我们就可以通过调用线程分离函数来使线程退出时,自动释放线程资源

需要额外注意的是,即使线程被分离,可线程出现异常时,仍然会影响进程,因为线程始终是在进程内执行的

在线程已经分离后,再有别的进程去调用join方法去等待其退出时,join方法会返回错误码,因为一个分离的线程是不能被其他线程回收或杀死的

pthread_detach函数

函数体:

      int pthread_detach(pthread_t thread);  
线程组内其他线程对目标线程进行分离
       pthread_detach(pthread_self());
线程自己分离

线程ID与进程ID

  • 一个程序下的所有线程同属于一个组,简称线程组,即多线程的进程,这些线程因为同属于一个进程,所以拥有相同的进程ID(PID),而每个线程又拥有各自的进程描述符(因为Linux下,线程被看做是轻量级进程),即线程ID
    void *thread_run(void *arg)
    {
        const char* msg = (const char*)arg;
        while(1){//通过死循环控制不让线程终止
        printf("I am %s ,my id is %d\n",msg,syscall(SYS_gettid));
        }
    }

    int main()
    {
        pthread_t tid1,tid2,tid3,tid4;
        //创建四个线程,该进程下就会拥有五个线程
        pthread_create(&tid1,NULL,thread_run,"thread1");
        pthread_create(&tid2,NULL,thread_run,"thread2");
        pthread_create(&tid3,NULL,thread_run,"thread3");
        pthread_create(&tid4,NULL,thread_run,"thread4");



        pthread_join(tid1,NULL);
        pthread_join(tid2,NULL);
        pthread_join(tid3,NULL);
        pthread_join(tid4,NULL);


    }  

查看当前的线程状况
这里写图片描述

  • LWP(Light Weighted Process)线程ID,同组的线程的进程ID是相同的,这两个概念不要搞混了
  • NLWP:线程组内线程的个数

线程ID不同于pthread_t类型的ID,线程ID是pid_t类型的变量,而且是用来唯一标识线程的一个整形变量,pthread_t类型的ID只是一个地址

为什么有两个thread ID

线程库实际上由两部分组成:内核的线程支持+用户态的库支持(glibc)。Linux在早期内核不支持线程的时候,glibc就在库中(用户态)以线程(就是用户态线程)的方式支持多线程了。POSIX thread只对用户编程的调用接口作了要求,而对内核接口没有要求。linux上的线程实现就是在内核支持的基础上,以POSIX thread的方式对外封装了接口,所以才会有两个ID的问题。

Linux线程浅析[线程的同步和互斥之线程读写锁]

Linux线程浅析[线程的同步和互斥之线程读写锁] 读写锁的出现是为了解决互斥锁的弊端 使用上述Linux线程浅析[线程的同步和互斥之线程互斥锁]的案例来进行解释吧,即针对上述案例中的银行存取款的...
  • qq_29924041
  • qq_29924041
  • 2017-03-31 22:27:10
  • 1066

浅析几种线程安全模型

多线程编程一直是老生常谈的问题,在Java中,随着JDK的逐渐发展,JDK提供给我们的并发模型也越来越多,本文摘取三例使用不同原理的模型,分析其大致原理。COW之CopyOnWriteArrayLis...
  • FYGu18
  • FYGu18
  • 2018-02-11 00:00:00
  • 512

JAVA线程浅析(二)

多线程浅析(二)        JAVA中多线程是抢占式的运行方式,哪个线程抢占到时间片,哪个线程就先运行。而线程调度是按照某种原则选择一个线程使它占有处理器运行,线程调度是操作系统的核心,线程调度...
  • java_study_zjh
  • java_study_zjh
  • 2017-04-24 15:56:03
  • 76

Linux进程调度分析

Linux进程调度分析
  • Li_Ning_
  • Li_Ning_
  • 2016-06-12 15:50:45
  • 1593

Linux — 浅析线程以及多线程的同步与互斥

线程 链接:http://blog.csdn.net/ctthuangcheng/article/details/8914712 关于linux线程 在许多经典的操作系统教科书中,...
  • Dawn_sf
  • Dawn_sf
  • 2017-06-04 23:02:15
  • 732

linux线程同步浅析——睡眠与唤醒的秘密

http://blog.csdn.net/baiduforum/archive/2010/04/12/5475284.aspx一个程序问题 之前写过这样一个C程序:模块维护一个工作线程、提供一组调用接...
  • walterxia
  • walterxia
  • 2011-03-10 00:14:00
  • 755

Linux下线程简单使用

  • 2017年01月24日 22:12
  • 2KB
  • 下载

linux 进程和线程

  • 2017年08月05日 10:34
  • 125KB
  • 下载

Linux下C语言编程——线程

  • 2010年07月24日 12:04
  • 35KB
  • 下载

linux线程的基本概念

  • 2009年10月27日 10:03
  • 37KB
  • 下载
收藏助手
不良信息举报
您举报文章:浅析Linux下的线程
举报原因:
原因补充:

(最多只允许输入30个字)