Java多线程系列(3)
在Java多线程系列(1)我们提到过有关线程的基本定义,接下来我们具体讲解。
定义
进程:进程是计算机进行资源(CPU,IO设备,磁盘等都是计算机中的资源)分配的基本单位。通俗的说:在电脑上运行的一应用就是一个进程,比如说爱奇艺播放器,qq等都是一个进程。
线程:线程是CPU执行和调度的基本单位。
关系:每个进程可以有多个线程,线程之间共享进程的各种资源。每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
线程分类
-
用户级线程(User-Level Thread)
用户线程:用户线程指不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。
优点:
(1) 线程的调度不需要内核直接参与,控制简单。
(2) 同一进程中只能同时有一个线程在运行,如果有一个线程使用了系统调用而阻塞,那么整个进程都会被挂起,可以节约更多的系统资源。
缺点:
(1) 一个用户级线程的阻塞将会引起整个进程的阻塞。
(2)它不能像内核级线程一样更好的运用多核CPU。
2.内核级线程(Kernel-Level Thread)(守护线程)
内核线程(kernel-level threads)指需要内核的参与,由内核完成线程的调度。其依赖于操作系统核心,由内核的内部需求进行创建和撤销。(我们看不见的,如java中的垃圾回收线程)
优点:
(1)当有多个处理机时,一个进程的多个线程可以同时执行。
(2) 由于内核级线程只有很小的数据结构和堆栈,切换速度快,当然它本身也可以用多线程技术实现,提高系统的运行速率。
缺点:
(1) 线程的调度和管理在内核实现,在控制权从一个线程传送到另一个线程需要用户态到内核态再到用户态的模式切换,比较占用系统资源。(就是必须要受到内核的监控)
用户级空间和内核级空间关系如下图所示:
用户级线程内核级线程的关系:
一个完整的程序在执行期间就有两个部分组成,即可以初略的理解为一边是用户态线程,另外一边是内核态线程。
内核线程是实际获得cpu资源并执行的线程。用户线程想要执行必须被调度和某个内核线程绑定,然后由内核线程再去竞争cpu资源来执行应用程序。
以下是用户级线程和内核级线程的区别:
(1)用户级线程的创建、撤消和调度不需要OS内核的支持,是在语言(如Java)这一级处理的;而内核支持线程的创建、撤消和调度都需OS内核提供支持,而且与进程的创建、撤消和调度大体是相同的。
(2)用户级线程的程序实体是运行在用户态下的程序,而内核支持线程的程序实体则是可以运行在任何状态下的程序。
(3)内核支持线程是OS内核可感知的,而用户级线程是OS内核不可感知的。
线程的生命周期
参考:https://blog.csdn.net/xiaosheng900523/article/details/82964768
线程的上下文切换
Java为什么需要支持并发?
1.充分利用多核CPU的资源,让每一个CPU都去工作。
2.提升系统性能,让系统支持高并发。
并发的缺点?
高并发的意味着线程创建销毁开销加大、上下文切换非常频繁(耗费时间,用户的体验性不好)。
时间片:多任务系统往往需要同时执行多道作业。作业数往往大于机器的CPU数,然而一颗CPU同时只能执行一项任务,如何让用户感觉这些任务正在同时进行呢? 操作系统的设计者 巧妙地利用了时间片轮转的方式。时间片是CPU分配给各个任务(线程)的时间!
线程上下文
线程上下文是指该线程运行到在某一时间点时,由于其他线程的抢占了cpu的使用权限或者自己让出CPU的使用权,导致此时该线程阻塞,此时CPU 寄存器和程序计数器里保存的就是该线程运行的状态。CPU通过时间片分配算法来循环执行任务(线程),因为时间片非常短,所以CPU通过不停地切换线程执行。因此单CPU线程切换更频繁,所以多核CPU一定程度上可以减少线程的上下文切换。
上下文切换
CPU通过分配时间片来执行任务,当一个任务的时间片用完,就会切换到另一个任务。在切换之前会保存上一个任务的状态,当下次再切换到该任务,就会加载这个状态。任务从保存到再加载的过程就是一次上下文切换。
- 线程切换,同一进程中的两个线程之间的切换
- 进程切换,两个进程之间的切换
- 模式切换,在给定线程中,用户模式和内核模式的切换
什么时候会发生上下文切换?
1.自发性上下文切换
通过调用下列方法会导致自发性上下文切换:
- Thread.sleep()
- Object.wait()
- Thread.yeild()
- Thread.join()
- LockSupport.park()
2.非自发性的上下文切换
- 切出线程的时间片用完
- 有一个比切出线程优先级更高的线程需要被运行
- 虚拟机的垃圾回收动作
上下文切换的开销
上下文切换的开销包括直接开销和间接开销。
直接开销有如下几点:
- 操作系统保存回复上下文所需的开销
- 线程调度器调度线程的开销
间接开销有如下几点:
- 处理器高速缓存重新加载的开销
- 上下文切换可能导致整个一级高速缓存中的内容被冲刷,即被写入到下一级高速缓存或主存