并发编程基本概念
# 并发编程基本概念
# 进程与线程的区别
进程:进程是程序的一次执行过程,是系统允许程序的基本单位。我们运行的QQ音乐、英雄联盟、笔记本都是一个进程。
线程:线程时比进程更小的执行单位,一个进程在其执行的过程中可以产生多个线程,与进程不同的是同类的多个线程共享进程的堆和方法区的资源,每个线程有自己的程序计数器、虚拟机栈和本地方法栈。
在Java中,当我们启动main函数时其实就启动了一个JVM进程,而main函数所在的线程就是这个进程的一个线程,也称主线程。
线程与进程最大的不同在于,进程基本上是独立的,而各线程则不一定,因为同一个进程中的线程极有可能互相影响。线程执行开销小,但不利于资源的管理和保护,进程则相反。
# 并发与并行的区别
串行:一次只能执行任务,依次执行各个任务。
并行:单位时间内,多个任务同时执行。
多个CPU同时执行多个任务,多个人同时做多个不同的事
并发:同一时间段,多个任务都在执行(单位时间内不一定同时执行)。
一个CPU上同时执行多个任务,线程实际还是串行的,操作系统的任务调度器,将cpu时间片分给不同的线程使用,cpu在线程之间切换的非常块,感觉像是同时允许的,微观串行,宏观并行。
对于多核cpu,多线程可以同时运行。
# 线程的生命周期和状态
- 初始状态new:刚刚创建,还没有调用start()方法。
- 运行状态RUNNABLE:Java线程将操作系统中的就绪和运行两种状态笼统称为"运行状态"。
- 阻塞状态BLOCKED:线程阻塞于锁。
- 等待状态WAITING:当前线程需要等待其他线程做出一些特定动作(通知或中断)。
- 超时等待状态TIME_WAITING:可以在指定时间自行返回。
- 终止状态TERMINATED:当前线程已经执行完毕。
运行状态RUNNABLE,分为运行中和就绪两种状态,就绪状态的线程获得CPU的时间片(timeslice)后就处于运行中了。
# JVM没有区分READY和RUNNING的原因
现在的时分(time-sharing)多任务(multi-task)操作系统通常都是用时间分片方式进行抢占式轮转调度。整个时间分片通常很小,一个线程一次最多只能在CPU上运行10-20ms,时间片用完后就要被切换下来放入调度队列,也就是回到ready状态,因为线程切换的如此之快,区分这两种状态就没什么意义了。
# 上下文切换
单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片实现这个机制。时间片是CPU分给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是是几毫秒(ms)。
CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。