并发编程之什么是线程

什么是线程

现代操作系统在运行一个程序时,会为其创建一个【进程】。例如,启动一个Java程序,操作系统就会创建一个Java进程。现代操作系统调度CPU的最小单元是线程,也叫轻量级进程(Light Weight Process)。在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。处理器在这些线程上高速切换,让使用者感觉到这些线程在同时执行。

线程的实现可以分为两类:

  1. 用户级线程(User-Level Thread)
  2. 内核线线程(Kernel-Level Thread)

用户空间与内核空间

在理解线程分类之前需要先了解系统的用户空间与内核空间两个概念。

  • 用户空间是普通应用程序可访问的内存区域。用户空间只能执行简单的运算,不能直接调用系统资源,必须通过系统接口,才能向内核发出指令。
  • 内核空间是操作系统内核访问的区域,独立于普通的应用程序,是受保护的内存空间。内核空间可以执行任意命令,调用系统的一切资源。

虚拟地址分配

以32位操作系统举例,它的寻址空间为4G(2的32次方),也就是内存空间为4G(64位操作系统分配方式不一样,不过这不重要)。操作系统将这4G可访问的内存空间分为二部分,一部分是内核空间,另一部分是用户空间。

  1. 用户空间:从 0x00000000 到 0xC0000000 的线性地址为用户空间,可由用户代码和内核代码进行引用,总共3G。
  2. 内核空间:从 0xC0000000 到 0xFFFFFFFFF 的线性地址为内核空间,只能由内核代码进行访问,总共1G。

用户态和内核态

当进程/线程运行在内核空间时就处于内核态,而进程/线程运行在用户空间时则处于用户态。

用户态,内核态的切换

linux系统中,不同的操作具有不同的权限,有些操作只有在内核空间才能进行。

所有用户程序都是运行在用户态的,但是有时候程序确实需要做一些内核态的事情,例如读取文件数据(所有I/O操作都直接或间接的通过内核空间),而唯一可以做这些事情的就是操作系统,所以此时程序就需要向操作系统请求以程序的名义来执行这些操作,这个时候就要切换到内核态。这种操作结束后,再切换到用户态。

用户线程与内核线程

用户线程(ULT)

不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心。

  • 应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。
  • 不需要用户态/核心态切换, 速度快
  • 这里的处理器时间片分配以进程为基本单位,所以每个线程执行的时间相对减少。

主要缺点:

操作系统内核不知道多线程的存在,因此一个线程阻塞将使得整个进程阻塞(包括它的所有线程)。

内核线程(KLT)

线程的所有管理操作都是由操作系统内核完成的。

  • 内核保存线程的状态和上下文信息,当一个线程执行了引起阻塞的系统调用时,内核可以调度该进程的其他线程执行。
  • 在多处理器系统上,内核可以分派属于同一进程的多个线程在多个处理器上运行,提高进程执行的并行度。
  • 大多数市场上的操作系统,如Windows, Linux等都支持内核级线程。

主要缺点:

  1. 数量有限,无法处理需要大量线程的任务
  2. 需要内核完成线程的创建、调度和管理,会涉及到内核态和用户态的切换,对资源消耗比较大,比起用户级线程会慢很多

原理区别图

  • 用户线程模式,线程不通过内核调度,线程表在进程中维护,处于用户空间
  • 内核线程模式,线程通过来内核调度,线程表在内核中维护,处于内核空间

Java线程对应用户线程还是内核线程

java线程对应的是内核线程,而不是用户线程!

Java里的线程是由JVM来管理的,JVM线程跟内核线程有一一相应的关系,也就是说当程序中创建一个java线程时,操作系统还会创建一个相应的内核线程,之后线程的调度全然交给了操作系统内核。

当然,JVM还保留了一些策略足以影响到其内部的线程调度。

Java线程生命周期

以一张图表示:

什么是并发

首先明确一点:并发不是并行!

并发任务交替进行假设现在有一个CPU核心,当同时跑多个线程时,真实系统环境下不可能同时两个线程在跑,同一时刻只能有一个线程在真正执行。操作系统不断地切换CPU时间片,只有分配到CPU时间片的线程能真正执行,通过这种方式来达到多个线程同时跑的功能。这个就是并发。

当然,如果有多个CPU核心,则每个CPU核心上都是这样的操作。

并行:并行是真正意义上的“同时进行”。如果系统内只有一个CPU,而使用多线程时,那么真实系统环境下不能并行。

并发的优点

  • 充分利用CPU的计算能力
  • 方便进行业务拆分,提升应用性能

并发产生的问题

  • 高并发场景下,导致频繁的上下文切换
  • 临界区线程安全问题,容易出现死锁的,产生死锁就会造成系统功能不可用 
  • 其它

线程上下文切换

CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值