Linux应用学习——多线程

多线程

Linux应用学习——多线程_第1张图片

PART1——线程相关概念

​ 线程时参与系统调度的最小单位。被包含在进程之中,是进程中的实际运行单位。一个进程可以创建多个线程,多个线程实现并发运行,每个线程执行不同的任务。

  • 线程时最基本的运行单位,而进程不能运行,真正运行的是进程中的线程
  • 可以认为进程是一个容器,包含了线程运行所需的数据结构、环境变量
  • 其他线程都是由主线程创建
  • 主线程通常会在最后结束运行,执行各种清理工作
  • 同一个进程中的多个线程将共享进程中的全部系统资源,如虚拟地址空间、文件描述符和信号处理等
  • 同一个进程的多个线程之间可以并发执行

1.1 进程与线程

  • 进程间切换开销大
  • 进程间通信麻烦
  • 进程创建速度比线程慢
  • 线程编程难度高

1.2 并行与并发

  • 串行
  • 并行
  • 并发

1.3 线程ID

  • 每个线程都有其对应的标识

  • 线程ID只有在它所属的进程上下文才有意义

  • 通过pthread_t pthread_self(void)获取自己的线程ID

  • 通过int pthread_equal(pthread_t t1,pthread_t t2)检查两个线程ID是否相等

PART2——线程使用

2.1 创建线程

  • 应用程序可以通过int pthread_creat(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine)(void *),void *arg)来创建一个线程

    • 新创建的线程的线程ID会保存在参数thread所指向的内存中

    • 线程的属性

    • 新创建的线程从start_routine函数开始运行

    • 传递给送start_routine函数的参数

    • 创建成功是返回0

  • 应用程序中使用pthread_creat创建线程后,编译是要指定-lpthread

2.2 终止线程

  • 线程的start_routine函数执行return语句并返回指定值,返回值就是线程的退出码

  • 线程调用void pthread_exit(void *retval)函数来终止调用它的线程

  • 调用pthread_cancel()取消线程

2.3 回收线程

  • 应用程序通过调用int pthread_join(pthread_t thread,void **retval)函数来阻塞等待线程的终止

    • thread等待指定线程终止

    • **retval如果被pthread_exit()终止,则将其退出状态赋值给retval,如果被pthread_cancel()终止,则将PTHREAD_CANCELED放在retval中

  • 线程之间可以互相进行pthread_join(),线程之间是对等的

  • 不能以非阻塞的方式调用pthread_join()

  • 可以通过int pthread_detach(pthread_t thread)将指定线程进程分离,此时线程终止时系统就能够自动回收线程资源并将其移除

    • 设置为分离线程后,便不能在恢复到之前的状态,此过程不可逆

    • 设置为分离线程后,便不能在用pthread_join()回收资源,会出错

  • 可以通过

    void pthread_cleanup_push(void(*routine)(void *),void *arg)

    void pthread_cleanup_pop(int execute)

    分别添加线程清理函数和移除线程的清理函数,成对出现

    • 当线程调用pthread_exit()退出时,添加的清理函数才会被执行

    • 线程响应pthread_cancel()时,添加的清理函数才会被执行

    • 用非零参数调用pthread_cleanup_pop()时,添加的清理函数才会被执行,参数为0时,清理函数不会执行,只会将最顶层的函数移除

2.4 取消线程

  • 通过int pthread_cancel(pthread_t thread)要求一个线程立即终止/退出

  • pthread_cancel()调用后,不会等待目标线程的退出,直接返回

  • 通过int pthread_setcancelstate(int state,int *olestate)设置线程取消的状态

    • state可以设置为:

      • PTHREAD_CANCEL_ENABLE线程可以被取消,默认值

      • PTHREAD_CANCEL_DISABLE线程不可被取消,会将请求挂起,直到取消状态变为PTHREAD_CANCEL_ENABLE

    • olestate,将线程之前的状态保存在此,如果不关心返回状态则可以设置为NULL

  • 通过int pthread_setcanceltype(int type,int *oldtype)设置线程取消的类型

    • type可以设置为:

      • PTHREAD_CANCEL_DEFERRED当取消请求到来时,线程继续运行,直到运行到某个取消点,默认值

      • PTHREAD_CANCEL_ASYNCHRONOUS可能在任何时间点取消线程

  • 可以通过man 7 pthreads查看可以作为取消点的函数

  • 可以通过void pthread_testcancel(void)作为取消点

2.5 线程属性

2.5.1 使用
  • 如果使用默认属性则把pthread_attr_t *attr设置为NULL即可

  • 如果要设置线程属性需要通过int pthread_attr_init(pthread_attr_t *attr)对属性对象进行初始化操作,并在不需要时通过int pthread_attr_destory(pthread_attr_t *attr对属性对象进行销毁

2.5.2 线程栈属性
  • 通过int pthread_attr_setstack(pthread_attr_t *attr,void *stackaddr,size_t stacksize)对栈的起始地址和栈大小进行设置

  • 通过int pthread_attr_getstack(const pthread_attr_t *attr,void **stackaddr,size_t *stacksize)获取栈信息

  • 获取栈代大小pthread_attr_getstacksize()

  • 设置栈大小pthread_attr_gsetstacksize()

  • 获取栈地址pthread_attr_getstackaddr()

  • 设置栈地址pthread_attr_setstackaddr()

2.5.3 分离状态属性
  • 设置分离属性

    int pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate)

  • 获取分离属性

    int pthread_attr_getdetachstate(const pthread_attr_t *attr,int *detachstate)

  • detachstate的值可以为:

    • PTHREAD_CREATE_DETACHED新建线程直接处于分离属性,系统自动回收资源

    • PTHREAD_CREATE_JOINABLE默认值,正常启动,可以被其他线程获取终止状态信息

2.6 线程安全

2.6.1 可重入函数
  • 如果一个函数被同一个进程的多个不同的执行流同时调用,诶此函数调用总是能产生正确的结果,这样的函数就是可重入函数

  • 可重入函数分为:

    • 绝对的可重入函数(函数内部仅仅操作函数内部定义的局部变量,除了使用栈上的变量以外不依赖任何环境变量,多个副本同时运行时,使用的分离的栈)

    • 带条件的可重入函数

  • 使用man 3 ctime查询时,MT-Safe指的是多线程安全,MT-Unsafe指的是线程不安全

2.6.2 线程安全函数
  • 一个函数被多个线程同时调用时,总会一直产生正确的结果,这样的函数被称为线程安全函数

  • 可重入函数一定是线程安全函数,线程安全函数不一定是可重入函数

  • 可以通过man 7 pthreads查询线程安全函数

2.6.3 一次性初始化
  • 应用程序如果需要只运行一次的函数,则可以通过

    int pthread_once(pthread_once_t *once_control,void(*init_routine)(void))使init_routine函数只运行一次

    通常pthread_once_t once_control = PTHREAD_ONCE_INIT;

  • 具体在哪个线程中执行是不确定的,有内核调度决定

2.6.4 线程特有数据
  • 为每一个调用线程分配属于该线程的私有数据区,为每一个调用线程分别维护一份变量的副本

  • 针对一些非线程安全的函数,使用线程特有数据将其变成线程安全函数

2.6.5 线程局部存储

PART3——线程同步

3.1 互斥锁

你可能感兴趣的:(Linux学习过程笔记,学习,java,jvm)