多线程

当引入线程后,进程可以看作是 资源的集合,线程可以看作是 执行单元线程之间共享进程的某些资源,比如文件描述符等等,这方便了线程之间的通信,每个线程都有自己的堆栈(因为线程的启动函数可能不同,甚至可能递归)

简单来说就是,同一个进程内的线程可以共享一些资源,每个线程都有自己的执行环境

初始线程(主线程)

主线程是特殊的(主线程就是第一个线程,就是main函数),大多数情况下,初始线程是运行在进程堆栈上的,普通线程的堆栈空间是受限的从主线程中返回会导致进程结束(所有线程终止),其他线程不会

并发系统的基本功能

  • 执行环境,并发实体(进程/线程) 的状态,并发系统需要有维护他们状态的方式

  • 调度,切换执行环境

  • 同步,协调访问共享资源

线程的两个操作

  • 连接

    在线程A中连接线程B,这句话的意思是,线程A会等待线程B结束后在执行(阻塞情况),线程结束时,可能会有返回值等信息,操作系统会假设这些是用户需要的,所以线程不会被回收,换句话说,线程即使做完了工作仍旧持有它所占有的资源(保留其虚拟内存),包括 堆栈 等等系统资源,这也叫做 僵尸线程

    一旦线程被连接,也就是说有其他线程接收返回值,那么这个线程就可以被回收了

  • 分离:

    分离的意思就是直接告诉操作系统,该线程无需被连接,换句话说就是返回值不需要传递给其他线程,这时候,操作系统会在线程结束工作后自动将其资源回收

线程能够自己分离自己或者让其他线程分离自己,但是不能自己连接自己,这会造成死锁,导致线程永远无法结束,只能让其他线程连接自己

线程的四个基本状态

1

2

线程在创建完毕后处于 就绪态,当 被调度 后转到 运行态,等待某些事件时转为 阻塞态,工作完成后或者被取消转到 终止态

阻塞态 可能是因为以下事件:

  • 试图加锁一个已经被锁住的互斥量
  • 等待某个条件变量
  • 执行无法立即完成的IO操作
  • 内存页错误

线程通常从启动函数中返回来终止自己,如果终止线程没有被分离或者连接,那么它将一直处于终止状态

需要注意的是,线程的返回值不要和它自己的堆栈相关,因为当线程返回时,其资源被释放,在去访问已经被释放的地址很可能会发生错误

线程的生命周期

线程创建 -> 线程启动 -> 运行和阻塞 -> 终止 -> 回收

线程安全和可重入

表示代码被多个线程调用不会有危害

可以通过以下方式实现线程安全:

(粒度渐细)

  • 函数调用串行化: 在进入函数前加锁

  • 保护临界代码:对访问共享数据的代码进行保护

  • 保护临界数据:对访问共享数据进行保护

  • 线程私有存储:每个线程可以独立存储各自的数据

可重入 就是用来形容 有效的线程安全,他应该避免对 静态数据 的依赖(全局变量、静态变量)

线程适用场景

  • 计算密集型:消耗CPU资源

  • IO密集型:消耗IO资源(计算机与外部设备进行数据交换)

 posted on 2024-12-29 22:07  Dylaris  阅读(32)  评论(0)    收藏  举报