简析Java并发

为什么使用多线程

众所周知,CPU、内存、I/O 设备的速度是有极大差异的,为了合理利用 CPU 的高性能,平衡这三者的速度差异,计算机体系结构、操作系统、编译程序都做出了贡献,主要体现为:

  • CPU 增加了缓存,以均衡与内存的速度差异;// 导致 可见性问题
  • 操作系统增加了进程、线程,以分时复用 CPU,进而均衡 CPU 与 I/O 设备的速度差异;// 导致 原子性问题
  • 编译程序优化指令执行次序,使得缓存能够得到更加合理地利用。// 导致 有序性问题

进程与线程

进程

进程是代码在数据集合上的一次运行活动(运行程序的动态过程),是系统进行资源分配和调度的基本单位,在Java中每开启一个虚拟机即为一个进程

线程

是进程的一个执行路径,系统运行的基本单位(CPU分配的进步单位),线程无法脱离进程存在,一个进程中至少有一个线程,也可以有多个线程共享进程的资源

即分配资源以进程为单位,但CPU资源被分配到线程

守护进程

Java线程分为守护线程和用户线程,守护线程维护JVM用户线程执行,例如GC线程

线程状态

NEW 新建
RUNNABLE 准备就绪
TERMINATED 结束
BLOCKED 阻塞
WAITING 等待
TIMED-WAITING 有限时等待
running 正在执行
线程操作
start 启动 新建一个线程
run 执行 执行线程
stop 终止 直接停止线程,容易发生数据不一致问题,不建议使用
interrupt 中断 线程接受中断通知,但是否中断由线程本身决定
wait 等待 对象方法,使用后进程在此对象上等待,直到某个线程调用该对象的notify方法。是线程之间进行通信的有效手段
notify 通知 参上
suspend 挂起 废弃,挂起不释放资源
resume 继续执行 废弃,与susend对应
join 等待线程结束 等待目标线程执行完毕,再执行
yield 谦让 静态方法,执行后会让出CPU,让出后继续参与CPU资源争夺

同步与异步

通常用来形容一次方法的调用,同步指方法调用一开始,必须等待方法返回后才能继续。异步方法调用后立刻返回,进行后面的操作,调用的方法返回由另一个线程通知调用者。

image-20210505214348914

并行与并发

并行

指多个CPU同时执行任务

并发

指在交替串行执行任务

并发等级

阻塞

在其他线程释放资源之前,线程一直等待,无法执行

无饥饿

如果线程之间存在优先级,线程调度偏向满足优先级高的线程。此时低优先级的线程可能不断被高优先级线程插队,无法获得资源,即饥饿状态

无障碍

最弱的非阻塞调度,线程都可以进入共享内存区域,检测是否发生线程冲突,一旦发现线程冲突,再进行回滚

可以通过一致性标记实现

无锁

所有线程都可以尝试对共享内存进行访问

无等待

在无锁要求一个线程在有限步骤内完成之外,要求所有线程都必须在有限步内完成,排除饥饿问题。

还可以进一步分为有界无等待和线程数无等待等几种类型

并发三要素

原子性

原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。

代码执行的基本逻辑单位

有序性

有序性:即程序执行的顺序按照代码的先后顺序执行。

涉及代码指令重排问题

可见性

可见性:一个线程对共享变量的修改,另外一个线程能够立刻看到。线程1对变量i修改了之后,线程2没有立即看到线程1修改的值

分类

img

优化

锁偏向

如果一个线程获得了锁,那么锁就进入偏向模型。当这个线程再次请求锁时,无需做任何同步操作

适用于几乎没有锁或同一个进程经常获得锁的情况

轻量级锁

将对象头部作为指针,指向持有锁的线程堆栈内部来判断线程是否持有对象锁。

自旋锁

JVM为了避免线程真实地再操作系统层面挂起,由于当前线程无法获得锁,暂时进行几次空循环

锁消除

在JIT编译时,通过对运行上下文扫描,去除不可能存在共享资源竞争地锁。

线程池

不断开启关闭线程反而增加了CPU和内存的开销。

对经常存在的线程通过线程池维护,减少开销。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享